为了账号安全,请及时绑定邮箱和手机立即绑定

golang 反射获取闭包函数指针

golang 反射获取闭包函数指针

Go
繁华开满天机 2021-12-27 15:17:11
请检查代码package mainimport (    "fmt"    "reflect")func main() {    factory := func  (name string) func(){        return func (){            fmt.Println(name)        }    }    f1 := factory("f1")    f2 := factory("f2")    pf1 := reflect.ValueOf(f1)    pf2 := reflect.ValueOf(f2)    fmt.Println(pf1.Pointer(), pf2.Pointer())    fmt.Println(pf1.Pointer() == pf2.Pointer())    f1()    f2()}结果:4199328 4199328truef1f2为什么到了闭包函数的同一个地址!或者如何获取唯一地址!
查看完整描述

3 回答

?
白衣染霜花

TA贡献1796条经验 获得超10个赞

函数指针表示函数的代码。而函数字面量创建的匿名函数的代码只会在内存中存储一次,无论返回匿名函数值的代码运行多少次。这意味着所有函数值(或更准确地说是函数指针)都将相同。


所以你无法区分存储在f1and 中的值f2:它们表示在调用它们时要执行的相同代码块。


存储在factory变量中的函数值返回的函数值是一个闭包。只要它可以访问,它所引用的环境(局部变量和函数参数)就会一直存在。在您的情况下,这意味着由于函数值 inf1和f2引用name封闭匿名函数的参数,只要函数值( inf1和f2)可访问,它们(来自多个调用的“它们”)将被保留。这是唯一使它们“不同”或独特的东西,但这是从“外部”看不到的。


你会继续打印name闭包中的地址吗,你会看到它们是闭包的多个值的不同变量,但是如果再次调用相同的闭包(函数值),它是相同的。首先修改闭包以打印以下地址:name


factory := func(name string) func() {

    return func() {

        fmt.Println(name, &name)

    }

}

并调用f1和f2多次:


f1()

f2()

f1()

f2()

输出:


f1 0x1040a120

f2 0x1040a130

f1 0x1040a120

f2 0x1040a130

如您所见,如果再次调用相同的闭包,name则保留name参数并再次使用相同的参数。


查看完整回答
反对 回复 2021-12-27
?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

https://golang.org/pkg/reflect/#Value.Pointer

如果 v 的 Kind 是 Func,则返回的指针是底层代码指针,但不一定足以唯一标识单个函数。唯一的保证是当且仅当 v 是一个 nil func 值时结果为零。


查看完整回答
反对 回复 2021-12-27
?
慕森王

TA贡献1777条经验 获得超3个赞

实际上,*func()在 Golang 中输入相当于void (*)(void)在 C 中输入。(我知道这一点是因为我经常使用 cgo。)

并且func()在围棋被定义为文字,这意味着它的类似的东西代表机器代码,而不是一个函数指针字节的BLOB。

请注意,Golang中一切都是按传递的,甚至 Go 中的函数也不例外。

var f1 func() = ...
reflect.ValueOf(f1)

当您这样做时,我认为您正在尝试获取名为 的代码块的前 8 个字节f1,这不是该函数的地址。

在 Go 中,您永远无法获得 a 的地址func()

因为 afunc()文字,文字没有地址。文字不在内存中的任何地方。所以你不能得到一个地址。


查看完整回答
反对 回复 2021-12-27
  • 3 回答
  • 0 关注
  • 286 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信