在 Go 中,有什么方法可以比较两个非 nil 函数指针来测试是否相等?我的平等标准是指针平等。如果不是,是否有什么特殊原因不允许指针相等?
到目前为止,如果我尝试以直接的方式执行此操作:
package main
import "fmt"
func SomeFun() {
}
func main() {
fmt.Println(SomeFun == SomeFun)
}
我明白了
./func-pointers.go:12: invalid operation: SomeFun == SomeFun (func can only be compared to nil)
据我了解,这种行为是最近才引入的。
我使用反射包找到了答案;但是 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())
}
输出:
true
false
最佳答案
请注意,平等和身份是有区别的。 Go1 中的运算符 ==
和 !=
正在比较等价的值(比较 channel 时除外),而不是身份。因为这些算子试图不混合平等和身份,所以 Go1 在这方面比 Go1 之前更加一致。
函数相等不同于函数标识。
在函数类型上不允许 ==
和 !=
的一个原因是性能。例如,以下闭包没有使用其环境中的任何变量:
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
和 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
}
关于go - 如何在最新的 Go 周刊中比较两个函数的指针相等性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9643205/