在Go语言中,当获取一个函数的名称时,为什么会有”-fm”后缀呢?

huangapple go评论92阅读模式
英文:

Why is there a "-fm" suffix when getting a function's name in 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)
}

输出结果是 main.(User).DummyHandler-fm

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

英文:

For the snippet below (runnable via the 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)
}

The output is main.(User).DummyHandler-fm.

Why is there a -fm at the end of the function name?

答案1

得分: 13

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

> 顺便说一下,这似乎在最新版本中变成了-fm。

> 你的代码得到了一个方法值。p.beHappy是绑定到特定值p的beHappy方法。这是通过创建一个函数闭包来实现的,闭包的代码需要一个名称。编译器恰好在末尾加上了fm作为名称,但它可以是任何不会与其他函数名冲突的东西。在Go中没有办法给这个函数命名,所以这个名称对于除了调试器或者像你看到的FuncForPC之外的任何其他事情都是无关紧要的。

似乎更好的获取方法名称的方法是直接引用该方法,像这样:

func main() {
  funcName((User).DummyHandler)
}

这将输出main.User.DummyHandler

英文:

Turns out u.DummyHandler is a method value and the compiler implements methods by creating a function closure and modifying the function name. To quote Ian here:

> This seems to have become -fm on tip, by the way.

> Your code is getting a method value. p.beHappy is the beHappy method
bound to the specific value of p. That is implemented by creating a
function closure, and the code for that closure needs a name. The
compiler happens to make that name by sticking fm on the end, but it
could be anything that won't conflict with any other function name.
There isn't any way to name that function in Go, so the name is
irrelevant for anything other than the debugger or, as you see,
FuncForPC.

It seems like a better way to get a method's name is to reference the method directly, like so:

func main() {
  funcName((User).DummyHandler)
}

This will output main.User.DummyHandler.

huangapple
  • 本文由 发表于 2015年10月4日 01:20:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/32925344.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定