一尘不染

golang反映获取闭包函数指针

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

为什么要到达关闭函数的相同地址!或如何获得唯一的地址!


阅读 310

收藏
2020-07-02

共1个答案

一尘不染

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

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

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

您会继续打印并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参数,并再次使用相同的参数。

2020-07-02