我有以下代码段:
type F func()
type I interface {}
func A() {}
func B() {}
func test() {
var a interface{} = A
var b interface{} = B
if A == B { // 1. Compile error
// Code
}
if a == b { // 2. No compile error
// Code
}
}
如果函数不具有可比性且接口具有可比性,为什么我可以为接口类型分配函数?
-
澄清我的问题另一个代码段:
type I interface {
DoSomething()
}
type F func()
func (f F) DoSomething() {
f()
}
func A() {
fmt.Println("A")
}
func B() {
fmt.Println("B")
}
func test() {
var _a F = A
var _b F = B
var a I = _a
var b I = _b
if a == b { // 2. No compile error but panic
// Code
}
}
在我看来,我可以通过简单的任务打破类型系统。
我不建议功能应该具有可比性。我的问题是:
答案 0 :(得分:5)
这就是语言的定义方式。来自spec:
界面值具有可比性。如果两个接口值具有相同的动态类型和相同的动态值,或者两者都具有值
nil
,则它们相等。
如果该类型的值不具有可比性,则对具有相同动态类型的两个接口值进行比较会导致运行时混乱。
功能值无法比较。但是,作为一种特殊情况,可以将函数值与预先声明的标识符
nil
进行比较。
这解释了为什么示例中的第一个if
语句在编译时失败,以及为什么第二个语句在运行时失败。
答案 1 :(得分:2)
引用Ian Lance Taylor's message 来自Go邮件列表上的this thread:
2016年11月23日星期三上午7点,T L写道:
2016年11月23日星期三下午10:35:59 UTC + 8,Axel Wagner写道:
所以,你的建议是,让功能具有可比性,但有 比较总是假的(除非与nil相比)?怎么会这样 有用且不完全混淆?例如怎么会不会导致 人们问这里,每周一次,为什么(
os.Open == os.Open) == false
或 这样的事情?不,我不是
os.Open != os.Open
,他们是同一个问题,所以他们是 等于。即使这个看似简单的陈述也不清楚。现在去支持
-buildmode=shared
和-linkshared
,意味着Go程序可以链接一组自己用Go编写的共享库。 在此模式下运行时,可以轻松显示os.Open
等功能 在单个程序映像中多次,在不同的共享中 库。因此虽然os.Open == os.Open
可能总是合理的 是的,给定func F() func(string) (*os.File, error) { return os.Open }
然后不清楚是否
F() == os.Open
应该是true,因为
F
可能位于共享库中并且可能返回a 指向os.Open
的其他实例的指针。
这只是其中一个原因。 另见一个 - 关于闭包的函数值 使用相同的代码但关闭不同的变量 - explained in that same thread by Jesper Louis Andersen
我想补充说,整个帖子值得全面阅读和吸收。