接口如何可以比较,同时功能不是?

时间:2017-11-10 13:58:37

标签: go

我有以下代码段:

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
    }
}

在我看来,我可以通过简单的任务打破类型系统。

我不建议功能应该具有可比性。我的问题是:

  • 为什么界面在默认情况下具有可比性?
  • 为什么不能将接口标记为可比较的resp。没有可比性?
  • 为什么不能定义用户定义的相等性?
  • 这种语言设计的动机是什么?

2 个答案:

答案 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

我想补充说,整个帖子值得全面阅读和吸收。