Go version
go version go1.20.12 windows/amd64
Output of go env
in your module/workspace:
set GO111MODULE=on
set GOARCH=amd64
set GOBIN=
set GOCACHE=H:\Temp\_Go_\Cache
set GOENV=C:\Users\***\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=G:\Projects\Go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=G:\Projects\Go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=H:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=H:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.20.12
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=0
set GOMOD=G:\Projects\Go\src\github.com\vault-thirteen\SimpleBB\go.mod
set GOWORK=
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=C:\Users\***\AppData\Local\Temp\go-build***=/tmp/go-build -gno-record-gcc-switches
What did you do?
I get a name of a function with the following code:
fullName := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
For the method Ping
of a Server
class (type) it returns the following name:
github.com/vault-thirteen/SimpleBB/pkg/ACM.(*Server).Ping-fm
For some reason a -fm
postfix is added to the function's full name.
When I tested the package which gets name of a function locally -- there was no -fm
postfix and all the tests of this code pass normally.
-
Why does a name contain the minus (hyphen) sign which can not be used for identifiers in Go language ?
-
What does the
fm
mean ? -
How do I get a normal function name without
-fm
postfix ?
What did you see happen?
I saw github.com/vault-thirteen/SimpleBB/pkg/ACM.(*Server).Ping-fm
.
What did you expect to see?
I expected to see the same function name as in tests of the method, i.e. a normal name of a function without any postfixes.
Comment From: Jorropo
Similar to #24488
Comment From: seankhliao
what's f
Comment From: vault-thirteen
what's
f
I suppose that it is a question.
f
is simply a function.
A simple test demonstrating this effect can be found here: https://github.com/vault-thirteen/JSON-RPC-M1/blob/main/RpcFunction_test.go#L18
I had to add another stage of function name parsing into the tested function located here: https://github.com/vault-thirteen/JSON-RPC-M1/blob/main/RpcFunction.go#L42
If I do not split the name with a hyphen, I get a strange function name like Abc-fm
which is not what I expect when I pass a function named Abc
.
Comment From: mauri870
I think this is expected. The compiler inserts the -fm suffix as the closure name (that is the way methods are implemented) and the suffix prevents collisions with existing function names. The function name has no real use outside of debuggers and maybe FuncForPC.
Comment From: vault-thirteen
@mauri870 , The function which I tested is not a closure, it is a class method, or a type method if we speak about Go language. https://github.com/vault-thirteen/JSON-RPC-M1/blob/main/RpcFunction_test.go#L11C22-L11C22
Comment From: mauri870
@vault-thirteen The way method sets are implemented, the -fm
suffix is added by the compiler to differenciate between the same method in T.M
and (*T).M
, so they have distinct method symbols. See https://go.dev/play/p/fq0dFnO9j_S
Comment From: vault-thirteen
@mauri870, Is this a documented feature of Go language ?
Comment From: mauri870
Not to my knowledge. It seems a rather internal detail about the compiler implementation. For instance, gccgo outputs the following for the program I linked above:
T.M: main.go..thunk0
(*T).M: main.go..thunk1
Reading the spec it only mentions that method sets must be unique.
Maybe the compiler folks can shine some line in here.
/cc @golang/compiler
Comment From: vault-thirteen
@mauri870 , thank you for the information.
For me it looks like Go language needs to introduce method overriding as in C++ and make a stable API and ABI, so that we do not see all these strange things any more. Who knows what will the postfix -fm
be tomorrow and will it be separated by a hyphen or a tilda or maybe something else ...
Comment From: mdempsky
The -fm suffix indicates a method value wrapper. (The suffix predates my involvement in the Go compiler, so I'm not sure what significance the letters "fm" have.)
I don't believe we currently guarantee what FuncForPC returns on method values. I'm open to defining it. (/cc @ianlancetaylor @alandonovan for gccgo and x/tools/go/ssa.)
Who knows what will the postfix -fm be tomorrow and will it be separated by a hyphen or a tilda or maybe something else ...
While we reserve the right to change internal symbol mangling, it's not something we do casually. We know it risks churn for end users. (Eg, I believe gc has used the -fm suffix since method values were added in Go 1.1.)
Comment From: vault-thirteen
@mdempsky , thank you for the details.
Comment From: ianlancetaylor
In my opinion this is an area where the compiler should retain flexibility. We shouldn't pin down precisely how runtime.FuncForPC
behaves given a reflection value. Among other things, we may want to specialize functions for various reasons based on profiling or other information, and we may want to give different specializations different names to make it easier for debuggers and disassemblers to understand what is going on.
So, closing. Please comment if you disagree.