请查看代码
package main
import (
"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 4199328
true
f1
f2
为什么要使用闭包功能的相同地址! 或者如何获得一个独特的地址!
答案 0 :(得分:4)
函数指针表示函数的代码。函数文字创建的匿名函数的代码只在内存中存储一次,无论返回匿名函数值的代码运行多少次。这意味着所有函数值(或更确切地说是函数指针)都是相同的。
因此,您无法区分f1
和f2
中存储的值:它们表示在调用它们时要执行的相同代码块。
存储在factory
变量中的函数值返回的函数值是一个闭包。只要可以访问,它所引用的环境(局部变量和函数参数)就能存活下来。在您的情况下,这意味着因为f1
和f2
中的函数值引用了封闭匿名函数的name
参数,所以它们(来自多个调用的“它们”)将保留为只要函数值(f1
和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
参数。
答案 1 :(得分:3)
https://golang.org/pkg/reflect/#Value.Pointer
如果v的Kind是Func,则返回的指针是底层代码 指针,但不一定足以识别单个函数 唯一。唯一的保证是当且仅当结果为零时 v是一个零函数值。
答案 2 :(得分:0)
实际上,Golang中的*func()
类型等同于C语言中的void (*)(void)
类型。(我知道这一点是因为我经常使用cgo。)
Go中的func()
被定义为文字,这意味着它就像是代表机器代码的字节团,而不是函数指针。
请注意,所有内容都是通过Golang中的 value 传递的,甚至Go中的函数也不例外。
var f1 func() = ...
reflect.ValueOf(f1)
当您这样做时,我认为您正在尝试获取名为f1
的代码块的前8个字节,而这不是该函数的地址。
在Go中,您永远不会获得func()
的地址。
因为func()
是文字,而文字没有地址。文字不位于内存中的任何位置。因此,您无法获得地址。