จะรับชื่อฟังก์ชันใน Go ได้อย่างไร?


104

ด้วยฟังก์ชั่นเป็นไปได้ที่จะได้รับชื่อหรือไม่? พูด:

func foo() {
}

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

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

ฉันได้รับแจ้งว่าruntime FuncForPCจะช่วยได้ แต่ฉันไม่เข้าใจวิธีการใช้งาน

คำตอบ:


194

ขออภัยที่ตอบคำถามของตัวเอง แต่พบวิธีแก้ไข:

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
แม้ว่าสิ่งนี้จะใช้งานได้ แต่อาจต้องใช้ความระมัดระวังบางประการที่นี่: เอกสารสำหรับ. Pointer () ระบุว่า "ถ้าชนิดของ v คือ Func ตัวชี้ที่ส่งคืนจะเป็นตัวชี้รหัสที่อยู่ข้างใต้ แต่ไม่จำเป็นต้องเพียงพอที่จะระบุฟังก์ชันเดียวโดยไม่ซ้ำกันเพียงอย่างเดียว รับประกันว่าผลลัพธ์จะเป็นศูนย์ก็ต่อเมื่อ v เป็นค่าศูนย์ func "
jochen

1
@jochen "not a single func" หมายความว่ามันสามารถส่งคืนผลบวกเท็จ (เช่นตัวชี้ของฟังก์ชันอื่น)?
ธีม

1
@themihai ฉันไม่รู้ประโยคที่ฉันยกมาคือเอกสารทั้งหมดที่golang.org/pkg/reflect/#Value ตัวชี้พูดเกี่ยวกับสิ่งนี้ แต่ดูเหมือนว่าคำพูดจะบ่งบอกว่าสามารถใช้ตัวชี้เดียวกันสำหรับฟังก์ชันที่แตกต่างกันได้ใช่หรือไม่? และถ้าเป็นกรณีนี้GetFunctionNameอาจคืนชื่อเดียวกันสำหรับฟังก์ชันที่แตกต่างกัน?
jochen

3
@jochen ฉันคิดว่ามันเกี่ยวข้องกับการปิด; หากคุณสร้างการปิดสองรายการที่มีฟังก์ชันพื้นฐานเหมือนกันการปิดจะเท่ากันแม้ว่าค่าที่ปิดจะต่างกันก็ตาม
Alex Guerra

9

ไม่ใช่สิ่งที่คุณต้องการเนื่องจากบันทึกชื่อไฟล์และหมายเลขบรรทัด แต่นี่คือวิธีที่ฉันทำใน Tideland Common Go Library ของฉัน ( http://tideland-cgl.googlecode.com/ ) โดยใช้แพ็คเกจ "รันไทม์":

// 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
นั่นไม่ช่วยจริงๆ ฉันไม่ต้องการรับข้อมูลเกี่ยวกับ call stack แต่เกี่ยวกับฟังก์ชันที่กำหนด ฉันเชื่อว่าคำถามจะได้รับคำตอบหากฉันรู้วิธีรับพีซีที่สอดคล้องกันโดยมีการอ้างอิงฟังก์ชัน (ถ้าเป็นไปได้)
moraes
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.