golang反映get闭包函数指针

时间:2016-03-21 08:55:58

标签: go

请查看代码

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

为什么要使用闭包功能的相同地址! 或者如何获得一个独特的地址!

3 个答案:

答案 0 :(得分:4)

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

因此,您无法区分f1f2中存储的值:它们表示在调用它们时要执行的相同代码块。

存储在factory变量中的函数值返回的函数值是一个闭包。只要可以访问,它所引用的环境(局部变量和函数参数)就能存活下来。在您的情况下,这意味着因为f1f2中的函数值引用了封闭匿名函数的name参数,所以它们(来自多个调用的“它们”)将保留为只要函数值(f1f2)可访问。这是使它们“不同”或独特的唯一因素,但这在“外部”是不可见的。

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

factory := func(name string) func() {
    return func() {
        fmt.Println(name, &name)
    }
}

多次致电f1f2

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()文字,而文字没有地址。文字不位于内存中的任何位置。因此,您无法获得地址。