golang反射获取闭包函数指针

dr.*_*sty 4 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()
}
Run Code Online (Sandbox Code Playgroud)

结果:

4199328 4199328
true
f1
f2
Run Code Online (Sandbox Code Playgroud)

为什么到了闭包函数的同一个地址!或者如何获得唯一地址?

icz*_*cza 8

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

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

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

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

factory := func(name string) func() {
    return func() {
        fmt.Println(name, &name)
    }
}
Run Code Online (Sandbox Code Playgroud)

并调用f1f2多次:

f1()
f2()
f1()
f2()
Run Code Online (Sandbox Code Playgroud)

输出:

f1 0x1040a120
f2 0x1040a130
f1 0x1040a120
f2 0x1040a130
Run Code Online (Sandbox Code Playgroud)

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


use*_*317 5

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

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