How to get the name of a function in Go?

65,508

Solution 1

I found a solution:

package main

import (
    "fmt"
    "reflect"
    "runtime"
)

func foo() {
}

func GetFunctionName(i interface{}) string {
    return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}

func main() {
    // This will print "name: main.foo"
    fmt.Println("name:", GetFunctionName(foo))
}

Solution 2

Not exactly what you want, because it logs the filename and the line number, but here is how I do it in my Tideland Common Go Library (http://tideland-cgl.googlecode.com/) using the "runtime" package:

// Debug prints a debug information to the log with file and line.
func Debug(format string, a ...interface{}) {
    _, file, line, _ := runtime.Caller(1)
    info := fmt.Sprintf(format, a...)

    log.Printf("[cgl] debug %s:%d %v", file, line, info)

Solution 3

Better Solution

I found a better solution, in this function down here you just simply pass a function and the output is gonna be simple and straight.

package main

import (
    "reflect"
    "runtime"
    "strings"
)

func GetFunctionName(temp interface{}) string {
    strs := strings.Split((runtime.FuncForPC(reflect.ValueOf(temp).Pointer()).Name()), ".")
    return strs[len(strs)-1]
}

And this is an example of how you use this:

package main

import "fmt"

func main() {
    fmt.Println(GetFunctionName(main))
}

And this is the answer you should expect:

main

Solution 4

By getting the function name of the previous caller:

import (
    "os"
    "runtime"
)

func currentFunction() string {
    counter, _, _, success := runtime.Caller(1)

    if !success {
        println("functionName: runtime.Caller: failed")
        os.Exit(1)
    }

    return runtime.FuncForPC(counter).Name()
}
Share:
65,508
moraes
Author by

moraes

Updated on July 08, 2022

Comments

  • moraes
    moraes almost 2 years

    Given a function, is it possible to get its name? Say:

    func foo() {
    }
    
    func GetFunctionName(i interface{}) string {
        // ...
    }
    
    func main() {
        // Will print "name: foo"
        fmt.Println("name:", GetFunctionName(foo))
    }
    

    I was told that runtime.FuncForPC would help, but I failed to understand how to use it.

  • moraes
    moraes almost 13 years
    That doesn't really help. I don't need to get information about the call stack, but about a given function. I believe the question would be answered if I knew how to get the corresponding pc given a function reference (if it is possible).
  • jochen
    jochen about 9 years
    While this seems to work, some care may be required here: the documentation for .Pointer() states "If v's Kind is Func, the returned pointer is an underlying code pointer, but not necessarily enough to identify a single function uniquely. The only guarantee is that the result is zero if and only if v is a nil func Value."
  • themihai
    themihai over 8 years
    @jochen does "not a single func" means that it could return false positives (i.e. the pointer of a different function) ?
  • jochen
    jochen over 8 years
    @themihai I don't know, the sentence I quoted is all the docs at golang.org/pkg/reflect/#Value.Pointer say about this. But the quote seems to indicate that one could get the same pointer for different functions, doesn't it? And if this is the case, GetFunctionName might return the same name for different functions?
  • Alex Guerra
    Alex Guerra almost 8 years
    @jochen I think this has to do with closures; if you create two closures that have the same underlying function, they will be equivalent even if the values they close over are different.
  • Gostega
    Gostega about 2 years
    What's the point of this? You're literally just returning the same string you passed to it. May as well just do fmt.Println("main")
  • Mahmood
    Mahmood about 2 years
    @Gostega I passed a function, not a string... This solution is actually what the question wanted. Read the question again.
  • Gostega
    Gostega about 2 years
    you're right, the question does ask that, I apologise. I think I read between the lines a bit on the question because it made no sense to me as written. It seems completely pointless to get the name of a function by passing the function's name. If one already has the name, just print it or use it, why pass that name to another function which simply returns the same name back.