在Go中获取函数名称时,为什么会有“ -fm”后缀?

Jas*_* Tu 4 reflection go

对于以下代码段(可通过Go Playground运行),

package main

import (
  "fmt"
  "net/http"
  "reflect"
  "runtime"
)

type User struct{}

var u = &User{}

func (_ User) DummyHandler(w http.ResponseWriter, r *http.Request) {}

func funcName(i interface{}) {
  p := reflect.ValueOf(i).Pointer()
  n := runtime.FuncForPC(p).Name()
  fmt.Println(n)
}

func main() {
  funcName(u.DummyHandler)
}
Run Code Online (Sandbox Code Playgroud)

输出为main.(User).DummyHandler-fm

为什么-fm函数名称的末尾有一个?

Jas*_* Tu 5

原来u.DummyHandler是方法值,编译器通过创建函数闭包并修改函数名称来实现方法。在这里引用伊恩:

顺便说一句,这似乎已经成为-fm了。

您的代码正在获取方法值。p.beHappy是绑定到p特定值的beHappy方法。这是通过创建函数闭包来实现的,并且该闭包的代码需要一个名称。编译器碰巧通过在末尾加上fm来命名,但这可能与任何其他函数名都不冲突。Go中没有任何方法来命名该函数,因此该名称与调试器或FuncForPC无关。

获得方法名称的更好方法似乎是直接引用该方法,如下所示:

func main() {
  funcName((User).DummyHandler)
}
Run Code Online (Sandbox Code Playgroud)

这将输出main.User.DummyHandler