Go'da bir işlevin adı nasıl alınır?


101

Bir işlev verildiğinde, adını almak mümkün mü? Söyle:

func foo() {
}

func GetFunctionName(i interface{}) string {
    // ...
}

func main() {
    // Will print "name: foo"
    fmt.Println("name:", GetFunctionName(foo))
}

Runtime.FuncForPC'nin yardımcı olacağı söylendi , ancak nasıl kullanılacağını anlayamadım.

Yanıtlar:


189

Kendi sorumu yanıtladığım için üzgünüm ama bir çözüm buldum:

package main

import (
    "fmt"
    "reflect"
    "runtime"
)

func foo() {
}

func GetFunctionName(i interface{}) string {
    return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}

func main() {
    // This will print "name: main.foo"
    fmt.Println("name:", GetFunctionName(foo))
}

2
Bu işe yarıyor gibi görünse de, burada biraz özen gösterilmesi gerekebilir: .Pointer () için dokümantasyon "v'nin Kind'i Func ise, döndürülen işaretçi bir temel kod göstericisidir, ancak tek bir işlevi benzersiz bir şekilde tanımlamak için yeterli değildir. garanti, sonucun sıfır olmasıdır, ancak ve ancak v bir sıfır func Değeri ise. "
jochen

1
@jochen "tek bir işlev değil", yanlış pozitifler döndürebileceği anlamına gelmiyor mu (yani farklı bir işlevin göstericisi)?
themihai

1
@themihai Bilmiyorum, aktardığım cümle golang.org/pkg/reflect/#Value.Pointer'daki tüm dokümanlar . Ancak alıntı, farklı işlevler için aynı göstericinin elde edilebileceğini gösteriyor, değil mi? Ve bu durumda, GetFunctionNamefarklı işlevler için aynı adı döndürebilir mi?
jochen

3
@jochen Bunun kapanışlarla ilgisi olduğunu düşünüyorum; Aynı temel işleve sahip iki kapanış oluşturursanız, kapattıkları değerler farklı olsa bile bunlar eşdeğer olacaktır.
Alex Guerra

9

Tam olarak istediğiniz şey değil, çünkü dosya adını ve satır numarasını günlüğe kaydediyor, ancak bunu Tideland Common Go Kitaplığımda ( http://tideland-cgl.googlecode.com/ ) "çalışma zamanı" paketini kullanarak şu şekilde yapıyorum :

// Debug prints a debug information to the log with file and line.
func Debug(format string, a ...interface{}) {
    _, file, line, _ := runtime.Caller(1)
    info := fmt.Sprintf(format, a...)

    log.Printf("[cgl] debug %s:%d %v", file, line, info)

1
Bu gerçekten yardımcı olmuyor. Çağrı yığını hakkında bilgi almam gerekmiyor, ancak belirli bir işlev hakkında. Bir fonksiyon referansı verilen karşılık gelen pc'yi nasıl elde edeceğimi bilseydim (mümkünse) sorunun cevaplanacağına inanıyorum.
moraes
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.