Go version
go version go1.22.2 darwin/arm64
Output of go env
in your module/workspace:
GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOOS='darwin'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOVCS=''
GOVERSION='go1.22.2'
GCCGO='gccgo'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/s8/7ynb7ztx01l2vgsdm0fty3t80000gn/T/go-build27692839=/tmp/go-build -gno-record-gcc-switches -fno-common'
What did you do?
package main
import (
"fmt"
"runtime"
"strings"
)
func GetFuncName() string {
pc := make([]uintptr, 10)
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
name := f.Name()
res := strings.Split(name, ".")
return res[len(res)-1]
}
func wrapper(name string) func() {
return func() {
// It should print "demo"
fmt.Println("function name: ", name)
}
}
func demo() {
// name is "demo"
name := GetFuncName()
defer wrapper(name)()
}
func main() {
demo()
}
What did you see happen?
run go build demo.go && ./demo
, output: function name: wrapper
run go build -gcflags "-N" demo.go && ./demo
, output: function name: demo
.
What did you expect to see?
The output is always demo
.
Comment From: randall77
runtime.FuncForPC
does not (and can't) handle inlining correctly. Use runtime.CallersFrames
for optimization-independent traceback.
That said, it is very strange that wrapper
appears as the output. It is not on the stack at all when runtime.Callers
is invoked.