Is it possible get information about caller function in Golang? For example if I have
func foo() { //Do something } func main() { foo() }
How can I get that foo
has been called from main
?
I'm able to this in other language (for example in C# I just need to use CallerMemberName
class attribute)
You can use Function. Caller to get the calling function.
A Function object's caller property returns the function that invoked the specified function. For strict, async function, and generator function callers, accessing the caller property throws an exception.
The function. caller property of the JavaScript function object returns the function that invoked the specified function. It returns null if the function “f” was invoked by the top-level code in JavaScript. For functions like strict functions, async functions and generator function this method returns null.
You can use runtime.Caller
for easily retrieving information about the caller:
func Caller(skip int) (pc uintptr, file string, line int, ok bool)
Example #1: Print caller file name and line number: https://play.golang.org/p/cdO4Z4ApHS
package main import ( "fmt" "runtime" ) func foo() { _, file, no, ok := runtime.Caller(1) if ok { fmt.Printf("called from %s#%d\n", file, no) } } func main() { foo() }
Example #2: Get more information with runtime.FuncForPC
: https://play.golang.org/p/y8mpQq2mAv
package main import ( "fmt" "runtime" ) func foo() { pc, _, _, ok := runtime.Caller(1) details := runtime.FuncForPC(pc) if ok && details != nil { fmt.Printf("called from %s\n", details.Name()) } } func main() { foo() }
expanding on my comment, here's some code that returns the current func's caller
import( "fmt" "runtime" ) func getFrame(skipFrames int) runtime.Frame { // We need the frame at index skipFrames+2, since we never want runtime.Callers and getFrame targetFrameIndex := skipFrames + 2 // Set size to targetFrameIndex+2 to ensure we have room for one more caller than we need programCounters := make([]uintptr, targetFrameIndex+2) n := runtime.Callers(0, programCounters) frame := runtime.Frame{Function: "unknown"} if n > 0 { frames := runtime.CallersFrames(programCounters[:n]) for more, frameIndex := true, 0; more && frameIndex <= targetFrameIndex; frameIndex++ { var frameCandidate runtime.Frame frameCandidate, more = frames.Next() if frameIndex == targetFrameIndex { frame = frameCandidate } } } return frame } // MyCaller returns the caller of the function that called it :) func MyCaller() string { // Skip GetCallerFunctionName and the function to get the caller of return getFrame(2).Function } // foo calls MyCaller func foo() { fmt.Println(MyCaller()) } // bar is what we want to see in the output - it is our "caller" func bar() { foo() } func main(){ bar() }
For more examples: https://play.golang.org/p/cv-SpkvexuM
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With