2012-05-24 32 views
11

Tôi đang cố gắng sử dụng hệ thống phản chiếu của Go để lấy tên của hàm nhưng tôi nhận được một chuỗi rỗng khi gọi phương thức Name trên kiểu của nó. Đây có phải là hành vi dự kiến?Lấy tên hàm sử dụng sự phản chiếu trong Golang

Đây là một ví dụ đơn giản về cách tôi tiếp cận vấn đề:

package main 

import "fmt" 
import "reflect" 

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

Dường như với tôi loại chính là 'hàm'. Những gì bạn mong đợi như một tên? –

+0

Đó là một điểm rất quan trọng. Ví dụ mã có lẽ không hoạt động, nhưng tôi nghĩ tên của câu hỏi là hợp lệ. – Laserallan

Trả lời

20

Các giải pháp là sử dụng FuncForPc mà trả về một *Func.

này trả "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) 
} 

Nếu bạn muốn "main", chỉ tokenize nó.

+0

Cảm ơn. Điều này giải quyết được vấn đề! – Laserallan

+9

Hoặc, không phản ánh, pc, _, _, _: = runtime.Caller (0) fmt.Println ("Tên hàm:" + runtime.FuncForPC (pc) .Name()) – Sonia

+0

Thú vị. Nhưng tôi đã giả định OP đang tìm kiếm một giải pháp tổng quát hơn, với bất kỳ chức năng nào. –

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()) 
} 

Output:

Tên của chức năng: main.main

Tên của chức năng: main.main
Tên của chức năng: main.x
Tên của chức năng: chính. y
Tên chức năng: main.z

+0

Cá nhân, tôi thích giải pháp của bạn (hoặc phần mở rộng của @ Koala3 trên giải pháp của riêng bạn), chủ yếu là vì nó cho phép gói gọn các cuộc gọi thời gian bên trong một hàm mà sau đó có thể được 'an toàn' triển khai ở nơi khác; nếu thời gian chạy Go hoạt động vì một số lý do thay đổi, thì toàn bộ mã cần được thay đổi chỉ tại một điểm. Ngoài ra, tránh phản chiếu là một thủ thuật gọn gàng, được thực hiện tốt! :) –

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

Lợi thế của việc giữ tên gói với tên hàm là, tất nhiên, có thể có một số hàm có cùng tên trong các gói khác nhau ... và sau đó bạn không có ý tưởng cái nào :) Thực tế, lý do chính để tôi tìm kiếm câu trả lời trên SO là vì tôi không chắc chắn chức năng nào của tôi đã gây ra lỗi và tôi cần theo dõi tên gói chính xác bên cạnh tên hàm ... Lưu ý rằng bạn cần import 'strings'and' filepath'as cho giải pháp của bạn để làm việc! –

Các vấn đề liên quan