2012-05-24 2749 views
11

我試圖使用Go的反射系統來檢索函數的名稱,但在調用其類型的Name方法時,我得到一個空字符串。這是預期的行爲?在Golang中使用反射獲取函數的名稱

這是我如何處理這個問題一個簡單的例子:

package main 

import "fmt" 
import "reflect" 

func main() { 
    typ := reflect.TypeOf(main) 
    name := typ.Name() 
    fmt.Println("Name of function" + name) 
} 
+1

在我看來,main的類型是'function'。你會期望什麼作爲一個名字? –

+0

這是一個非常重要的點。代碼示例應該可能不起作用,但我認爲問題的名稱是有效的。 – Laserallan

回答

20

的解決方案是使用FuncForPc返回一個*Func

這將返回"main.main"

package main 

import "fmt" 
import "reflect" 
import "runtime" 


func main() { 
    name := runtime.FuncForPC(reflect.ValueOf(main).Pointer()).Name() 
    fmt.Println("Name of function : " + name) 
} 

如果你想"main",只是記號化它。

+0

謝謝。這解決了問題! – Laserallan

+9

或者,沒有反映,pc,_,_,_:= runtime.Caller(0) fmt.Println(「函數名稱:」+ runtime.FuncForPC(pc).Name()) – Sonia

+0

有趣。但我假設OP正在尋找一種更通用的解決方案,並且具有任何功能。 –

25
package main 

import "fmt" 
import "runtime" 

func main() { 
    pc, _, _, _ := runtime.Caller(0) 
    fmt.Println("Name of function: " + runtime.FuncForPC(pc).Name()) 
    fmt.Println() 

    // or, define a function for it 
    fmt.Println("Name of function: " + funcName()) 
    x() 
} 

func funcName() string { 
    pc, _, _, _ := runtime.Caller(1) 
    return runtime.FuncForPC(pc).Name() 
} 

func x() { 
    fmt.Println("Name of function: " + funcName()) 
    y() 
} 

func y() { 
    fmt.Println("Name of function: " + funcName()) 
    z() 
} 
func z() { 
    fmt.Println("Name of function: " + funcName()) 
} 

輸出:

的功能名稱:main.main的功能

名稱:main.main
的功能名稱:main.x
的功能名稱:主。 y
功能名稱:main.z

+0

個人而言,我更喜歡你的解決方案(或@ Koala3的擴展在你自己的解決方案),主要是因爲它允許將運行時調用封裝在一個函數中,然後可以「安全」地部署到其他地方;如果Go運行時由於某種原因改變了功能,那麼整個代碼需要在一個地方改變。此外,避免反射是一個巧妙的技巧,做得好! :) –

2
import runtime 

func funcName() string { 
    pc, _, _, _ := runtime.Caller(1) 
    nameFull := runtime.FuncForPC(pc).Name() // main.foo 
    nameEnd := filepath.Ext(nameFull)   // .foo 
    name := strings.TrimPrefix(nameEnd, ".") // foo 
    return name 
} 
+0

使用函數名保持包名的好處當然是,有可能在不同的包中有多個具有相同名稱的函數......然後你不知道哪個是哪個:)事實上,我在SO上搜索這個答案的主要原因是因爲我不確定哪些函數導致了錯誤,並且我需要追蹤除函數名稱之外的精確包名... 請注意,您需要導入'字符串'和'文件路徑'以及您的解決方案的工作! –