背景

在 golang 中,往往需要获知当前的函数名及其调用者。

例如在监控场景,自动获取函数名的需求比较常见。

实现

直接上代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func FuncAndCallerFunc() (string, string) {
	pc := make([]uintptr, 15)
	n := runtime.Callers(2, pc)
	frames := runtime.CallersFrames(pc[:n])
	frame, more := frames.Next()
	var caller string
	if more {
		callerFra, _ := frames.Next()
		caller = callerFra.Function
	}
	if len(caller) == 0 {
		caller = "-"
	}

	return frame.Function, caller
}

测试一下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
type A struct{}

func main() {
	_f, _c := FuncAndCallerFunc()
	fmt.Printf("in func: %v, caller is: %v\n", _f, _c)
	a := A{}
	x(a)
}

func x(a A) {
	_f, _c := FuncAndCallerFunc()
	fmt.Printf("in func: %v, caller is: %v\n", _f, _c)
	a.print()
}

func (A) print() {
	_f, _c := FuncAndCallerFunc()
	fmt.Printf("in func: %v, caller is: %v\n", _f, _c)
}

输出为

1
2
3
in func: main.main, caller is: runtime.main
in func: main.x, caller is: main.main
in func: main.A.print, caller is: main.x

-EOF-