在围棋中,有没有办法比较两个非空函数指针来测试等价性?我的平等标准是指针相等.如果不允许,有什么特殊的原因不允许指针相等吗?

到目前为止,如果我试图以直截了当的方式做到这一点:

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)

据我了解,这一行为是最近引入的.


我已经使用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())
}

输出:

true
false

推荐答案

请注意,平等和身份是有区别的.GO1中的运算符==!=比较的是等价值(比较通道时除外),而不是同一性.因为这些运算符正在try not混合相等和同一性,所以在这方面go1比prego1更一致.

函数相等不同于函数标识.


函数类型上不允许==!=的一个原因是性能.例如,以下闭包未使用其环境中的任何变量:

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

不允许比较函数使编译器能够为闭包生成单个实现,而不是要求运行时(在运行时)创建新的闭包.因此,从性能的Angular 来看,不允许函数比较的决定是一个好的决定.


关于使用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
}

依赖于undefined behavior.不能保证程序将打印什么.编译器可以决定将SomeFunAnotherFun合并成单个实现,在这种情况下,第二打印语句将打印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
}

Go相关问答推荐

Makefile:现有文件上没有这样的文件或目录,不加载环境变量

如何模拟嵌入. FS?

Go Net/http路由

将类型定义为泛型类型实例化

golang有int32溢出吗?

如何将字节文件高效地读入int64切片?

如何为ANTLR4目标Go调试监听器

Global Thread-local Storage 在 Go 中的可行性和最佳实践

如何使用泛型将接口转换为指定类型

使用 unsafe.Pointer 将 struct point直接转换为另一个 struct 是否安全?

动态 SQL 集 Golang

regex.ReplaceAll 但如果替换则添加相同数量的字符

获取不带类型参数的泛型 struct 的类型名称

如何将一片十六进制字节转换为整数

如何使用 Go 获取 X11 中的窗口列表

为什么此代码在运行命令 error="exec: not started" 时出现错误?

无法建立连接,因为目标机器主动拒绝它 Golang

Unescape 在 rss 中两次逃脱了标题

go 堆栈跟踪:在某些函数调用参数或返回值之后的问题(?)标记是什么意思?

GOLANG 如何使用 http.FileServer 从模板目录加载某个 html 文件