在Go中,有没有办法比较两个非零函数指针来测试相等性?我的平等标准是指针平等。如果没有,是否有任何特殊原因不允许指针相等?
截至目前,如果我尝试以直截了当的方式做到这一点:
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
答案 0 :(得分:42)
请注意,平等和身份之间存在差异。 Go1中的运算符==
和!=
正在比较等价值(比较通道时除外),而不是标识。因为这些运算符正在尝试而不是来混合相等和身份,所以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
合并到一个实现中,在这种情况下,第二个print语句将打印true
。实际上,绝对不能保证第一个print语句会打印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
}
答案 1 :(得分:3)
解决方法取决于情况。我不得不改变几个比较功能的地方。在一次的情况下,我只是做了一些不同的事情,所以我不再需要比较它们了。在另一个案例中,我使用了一个struct来将函数与可比较的字符串相关联,比如,
type nameFunc struct {
name string
fval func()
}
我只需要比较几个函数,因此最简单的方法是保留这些结构的切片并根据需要扫描切片,比较名称字段和调度fval。如果你有很多,你可以使用地图。如果您的函数具有不同的签名,则可以使用接口,等等。
答案 2 :(得分:1)
现在不允许进行地图和函数值比较(除了 根据Go 1计划与nil比较。功能平等是 在某些上下文中有问题,并且映射相等性比较指针,而不是 地图的内容。
存在闭包时功能相等是有问题的(何时 是两个闭合相等?)