在最新的 Go 周刊中,如何比较两个函数的指针相等性?

2024-01-07

在 Go 中,有没有办法比较两个非零函数指针来测试相等性?我的平等标准是指针平等。如果不是,是否有任何特殊原因不允许指针相等?

截至目前,如果我尝试以直接的方式执行此操作:

package main

import "fmt"

func SomeFun() {
}

func main() {
    fmt.Println(SomeFun == SomeFun)
}

I get

./func-pointers.go:12: invalid operation: SomeFun == SomeFun (func can only be compared to nil)

据我了解,这种行为是最近引入的。


我使用 Reflect 包找到了答案;然而 Atom 在下面表明这实际上会产生未定义的行为。请参阅 Atom 的帖子以获取更多信息和可能的替代解决方案。

package main

import "fmt"
import "reflect"

func SomeFun() { }

func AnotherFun() { }

func main() {
    sf1 := reflect.ValueOf(SomeFun)
    sf2 := reflect.ValueOf(SomeFun)
    fmt.Println(sf1.Pointer() == sf2.Pointer())

    af1 := reflect.ValueOf(AnotherFun)
    fmt.Println(sf1.Pointer() == af1.Pointer())
}

Outputs:

true
false

请注意,平等和同一性之间存在差异。经营者== and !=Go1 中比较的是等价值(比较通道时除外),而不是同一性。因为这些运营商正在尝试not为了混合平等和同一性,Go1 在这方面比 Go1 之前更加一致。

函数相等与函数恒等不同。


不允许的原因之一== and !=关于函数类型的是性能。例如,以下闭包不使用其环境中的任何变量:

f := func(){fmt.Println("foo")}

禁止函数比较使编译器能够为闭包生成单个实现,而不需要运行时创建新的闭包(在运行时)。因此,从性能的角度来看,禁止函数比较的决定是一个很好的决定。


关于使用reflect包来确定函数身份,代码如下

func SomeFun()    {}
func AnotherFun() {}

func main() {
    sf1 := reflect.ValueOf(SomeFun)
    sf2 := reflect.ValueOf(SomeFun)
    fmt.Println(sf1.Pointer() == sf2.Pointer())  // Prints true

    af1 := reflect.ValueOf(AnotherFun)
    fmt.Println(sf1.Pointer() == af1.Pointer())  // Prints false
}

依靠未定义的行为。无法保证程序将打印什么内容。编译器可能会决定合并SomeFun and AnotherFun到单个实现中,在这种情况下,第二个打印语句将打印true。事实上,绝对不能保证第一个打印语句会打印true(在其他一些 Go1 编译器和运行时下,它可能会打印false).


您原来问题的正确答案是:

package main

import "fmt"

func F1() {}
func F2() {}

var F1_ID = F1  // Create a *unique* variable for F1
var F2_ID = F2  // Create a *unique* variable for F2

func main() {
    f1 := &F1_ID  // Take the address of F1_ID
    f2 := &F2_ID  // Take the address of F2_ID

    // Compare pointers
    fmt.Println(f1 == f1)  // Prints true
    fmt.Println(f1 == f2)  // Prints false
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在最新的 Go 周刊中,如何比较两个函数的指针相等性? 的相关文章

随机推荐