真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何在Go的函數(shù)中得到調(diào)用者的函數(shù)名

這篇文章主要講解了“如何在Go的函數(shù)中得到調(diào)用者的函數(shù)名”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“如何在Go的函數(shù)中得到調(diào)用者的函數(shù)名”吧!

企業(yè)建站必須是能夠以充分展現(xiàn)企業(yè)形象為主要目的,是企業(yè)文化與產(chǎn)品對(duì)外擴(kuò)展宣傳的重要窗口,一個(gè)合格的網(wǎng)站不僅僅能為公司帶來(lái)巨大的互聯(lián)網(wǎng)上的收集和信息發(fā)布平臺(tái),成都創(chuàng)新互聯(lián)面向各種領(lǐng)域:混凝土攪拌罐網(wǎng)站設(shè)計(jì)、全網(wǎng)營(yíng)銷推廣解決方案、網(wǎng)站設(shè)計(jì)等建站排名服務(wù)。


func Foo() {     fmt.Println("誰(shuí)在調(diào)用我?")     bar() } func Bar() {     fmt.Println("誰(shuí)又在調(diào)用我?") }

首先打印函數(shù)本身的名稱

最簡(jiǎn)單的方式就是硬編碼。 因?yàn)樵诰幾g之前,我們肯定知道打印的時(shí)候所在哪個(gè)函數(shù),但是更好的方式是編寫(xiě)一個(gè)通用的函數(shù),比如下面的例子:

package main import (     "fmt"     "runtime" ) func main() {     Foo() } func Foo() {     fmt.Printf("我是 %s, 誰(shuí)在調(diào)用我?\n", printMyName())     Bar() } func Bar() {     fmt.Printf("我是 %s, 誰(shuí)又在調(diào)用我?\n", printMyName()) } func printMyName() string {     pc, _, _, _ := runtime.Caller(1)     return runtime.FuncForPC(pc).Name() }

輸出結(jié)果:

我是 main.Foo, 誰(shuí)在調(diào)用我? 我是 main.Bar, 誰(shuí)又在調(diào)用我?

可以看到函數(shù)在被調(diào)用的時(shí)候,printMyName把函數(shù)本身的名字打印出來(lái)了,注意這里Caller的參數(shù)是1,  因?yàn)槲覀儗I(yè)務(wù)代碼封裝成了一個(gè)函數(shù)。

首先打印函數(shù)調(diào)用者的名稱

將上面的代碼修改一下,增加一個(gè)新的printCallerName的函數(shù),可以打印調(diào)用者的名稱。

func main() {     Foo() } func Foo() {     fmt.Printf("我是 %s, %s 在調(diào)用我!\n", printMyName(), printCallerName())     Bar() } func Bar() {     fmt.Printf("我是 %s, %s 又在調(diào)用我!\n", printMyName(), printCallerName()) } func printMyName() string {     pc, _, _, _ := runtime.Caller(1)     return runtime.FuncForPC(pc).Name() } func printCallerName() string {     pc, _, _, _ := runtime.Caller(2)     return runtime.FuncForPC(pc).Name() }

相關(guān)函數(shù)介紹

你可以通過(guò)runtime.Caller、runtime.Callers、runtime.FuncForPC等函數(shù)更詳細(xì)的跟蹤函數(shù)的調(diào)用堆棧。

1、func Caller(skip int) (pc uintptr, file string, line int, ok bool)

Caller可以返回函數(shù)調(diào)用棧的某一層的程序計(jì)數(shù)器、文件信息、行號(hào)。

0 代表當(dāng)前函數(shù),也是調(diào)用runtime.Caller的函數(shù)。1 代表上一層調(diào)用者,以此類推。

2、func Callers(skip int, pc []uintptr) int

Callers用來(lái)返回調(diào)用站的程序計(jì)數(shù)器, 放到一個(gè)uintptr中。

0 代表 Callers 本身,這和上面的Caller的參數(shù)的意義不一樣,歷史原因造成的。 1 才對(duì)應(yīng)這上面的 0。

比如在上面的例子中增加一個(gè)trace函數(shù),被函數(shù)Bar調(diào)用。

…… func Bar() {     fmt.Printf("我是 %s, %s 又在調(diào)用我!\n", printMyName(), printCallerName())     trace() } func trace() {     pc := make([]uintptr, 10) // at least 1 entry needed     n := runtime.Callers(0, pc)     for i := 0; i < n; i++ {         f := runtime.FuncForPC(pc[i])         file, line := f.FileLine(pc[i])         fmt.Printf("%s:%d %s\n", file, line, f.Name())     } }

輸出結(jié)果可以看到這個(gè)goroutine的整個(gè)棧都打印出來(lái)了:

/usr/local/go/src/runtime/extern.go:218 runtime.Callers /Users/yuepan/go/src/git.intra.weibo.com/platform/tool/g/main.go:34 main.trace /Users/yuepan/go/src/git.intra.weibo.com/platform/tool/g/main.go:20 main.Bar /Users/yuepan/go/src/git.intra.weibo.com/platform/tool/g/main.go:15 main.Foo /Users/yuepan/go/src/git.intra.weibo.com/platform/tool/g/main.go:10 main.main /usr/local/go/src/runtime/proc.go:210 runtime.main /usr/local/go/src/runtime/asm_amd64.s:1334 runtime.goexit

3、func CallersFrames(callers []uintptr) *Frames

上面的Callers只是或者棧的程序計(jì)數(shù)器,如果想獲得整個(gè)棧的信息,可以使用CallersFrames函數(shù),省去遍歷調(diào)用FuncForPC。

上面的trace函數(shù)可以更改為下面的方式:

func trace2() {     pc := make([]uintptr, 10) // at least 1 entry needed     n := runtime.Callers(0, pc)     frames := runtime.CallersFrames(pc[:n])     for {         frame, more := frames.Next()         fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)         if !more {             break         }     } }

4、func FuncForPC(pc uintptr) *Func

FuncForPC 是一個(gè)有趣的函數(shù), 它可以把程序計(jì)數(shù)器地址對(duì)應(yīng)的函數(shù)的信息獲取出來(lái)。如果因?yàn)閮?nèi)聯(lián)程序計(jì)數(shù)器對(duì)應(yīng)多個(gè)函數(shù),它返回最外面的函數(shù)。

它的返回值是一個(gè)*Func類型的值,通過(guò)*Func可以獲得函數(shù)地址、文件行、函數(shù)名等信息。

除了上面獲取程序計(jì)數(shù)器的方式,也可以通過(guò)反射的方式獲取函數(shù)的地址:

runtime.FuncForPC(reflect.ValueOf(foo).Pointer()).Name()

5、獲取程序堆棧

在程序panic的時(shí)候,一般會(huì)自動(dòng)把堆棧打出來(lái),如果你想在程序中獲取堆棧信息,可以通過(guò)debug.PrintStack()打印出來(lái)。比如你在程序中遇到一個(gè)Error,但是不期望程序panic,只是想把堆棧信息打印出來(lái)以便跟蹤調(diào)試,你可以使用debug.PrintStack()。

抑或,你自己讀取堆棧信息,自己處理和打印:

func DumpStacks() {     buf := make([]byte, 16384)     buf = buf[:runtime.Stack(buf, true)]     fmt.Printf("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf) }

參考 調(diào)試?yán)鳎篸ump goroutine 的 stacktrace。

利用堆棧信息還可以獲取goroutine的id, 參考: 再談?wù)劔@取 goroutine id 的方法

func GoID() int {     var buf [64]byte     n := runtime.Stack(buf[:], false)     idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0]     id, err := strconv.Atoi(idField)     if err != nil {         panic(fmt.Sprintf("cannot get goroutine id: %v", err))     }     return id }

感謝各位的閱讀,以上就是“如何在Go的函數(shù)中得到調(diào)用者的函數(shù)名”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)如何在Go的函數(shù)中得到調(diào)用者的函數(shù)名這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!


分享題目:如何在Go的函數(shù)中得到調(diào)用者的函數(shù)名
網(wǎng)頁(yè)URL:http://weahome.cn/article/ggihjs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部