How to get the current function name

For tracing purpose, I'd like to print out current function name, like the __FUNCTION__ macro in gcc.

So that when I have a function

func foo () {
   trace()
}

it will automatically print out Entering foo()... or something like that.


Solution 1:

[Note: Go 1.7+ recommends using runtime.CallersFrames instead of runtime.FuncForPC; another answer has an updated example].

Package runtime is your friend here:

func trace() {
    pc := make([]uintptr, 10)  // at least 1 entry needed
    runtime.Callers(2, pc)
    f := runtime.FuncForPC(pc[0])
    file, line := f.FileLine(pc[0])
    fmt.Printf("%s:%d %s\n", file, line, f.Name())
}

Solution 2:

Go 1.7 added some runtime functions to improve accessing stack frame information.

From the Go 1.7 Release Notes:

The new function CallersFrames translates a PC slice obtained from Callers into a sequence of frames corresponding to the call stack. This new API should be preferred instead of direct use of FuncForPC, because the frame sequence can more accurately describe call stacks with inlined function calls.

An improved example:

func trace2() {
    pc := make([]uintptr, 15)
    n := runtime.Callers(2, pc)
    frames := runtime.CallersFrames(pc[:n])
    frame, _ := frames.Next()
    fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}

Playground: https://play.golang.org/p/YkEN5mmbRld

Solution 3:

Here's a simpler version that doesn't need to allocate an array.

func trace() (string, int, string) {
    pc, file, line, ok := runtime.Caller(1)
    if !ok { return "?", 0, "?" }

    fn := runtime.FuncForPC(pc)
    if fn == nil { return file, line, "?" }

    return file, line, fn.Name()
}