Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible get information about caller function in Golang?

Tags:

go

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)

like image 436
Tinwor Avatar asked Feb 04 '16 22:02

Tinwor


People also ask

Which of the following methods can be used to get the caller of a function?

You can use Function. Caller to get the calling function.

What is the caller of a 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.

What is a caller in JavaScript?

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.


2 Answers

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() } 
like image 53
svenwltr Avatar answered Sep 28 '22 13:09

svenwltr


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

like image 21
Not_a_Golfer Avatar answered Sep 28 '22 11:09

Not_a_Golfer