golang interface

作者: 大漠狼道 | 来源:发表于2017-03-21 23:45 被阅读357次

    这个是常见的interface使用

    type Reader interface {
    Read(p []byte)(n int, err error)
    }
    
    func ValueOf(i interface{}) Value
    
    var xxx interface{}
    

    定义

    interface是方法集

    实现

    • 如果某类型的方法集是这个interface的超集,那么这个类型就实现了这个interface。简单来说,实现了这些方法就实现了这个接口,不需要像java等显示指出继承接口(implement),类似duck typing,能提供这个功能,那么就实现了这个接口。
    • 从另外一个角度来说,如果某个类型拥有某些方法集,那么这个类型隐性的实现了某些接口。

    例如:

    type callback func() error
    
    func (call callback)Error() string{
     err := call()
      return fmt.Srpintf("callback %v ", err)
    }
    

    那么callback也是个error,因为实现了error interface{},这里并没有显性的说明要实现error这个接口

    对于第二点,也很有意思。有的时候,可能会出现这种类似场合:
    两个第三方包的A,B类型都提供Format()方法,输入是interface类型,可能是A也可能是B,也可能是其他的,但是我们要format数据,怎么办呢?

    switch typ := src.(type) {
      case A:
        // A.Format()
      case B:
        // B.Format()
      default :
        // do something
    }
    但是有个问题,如果以后类型不断增加,怎么办?
    如果某个类型拥有某个方法集,那么就隐性的实现了某接口,这里共通的方法Format
    
    func DemoFormat( src interface{}){
      type Formater interface{
        Format()
      }
      formater, ok := src.(Formater)
      if ok {
        // formater.Format()
      } else {
        // 没有实现Format(),另外处理
      }
    }
    github上的一个例子:
    https://github.com/pkg/errors/blob/master/example_test.go#L176
    

    还有个特例,Empty interface{},这个也是Type,他的类型是interface{},相当于空的方法集,也就是任何类型都是他的超集,即都实现了空接口。相当于javascript中的Any,任何类型都可以赋值给Empty interface{}

    作为变量

    var xxx interface{}
    作为变量的时候,interface变量的底层有两个字段,一个是值,一个是method table,就是实现这个接口具体的方法集合。

    type errorDemo struct{}
    func (e errorDemo)Error()string{
      return "errorDemo error"
    }
    var err error = errorDemo{}
    

    这个时候,err的值就是errorDemo,方法集就func(e errorDemo)Error()string
    一个interface{}是有两个字段的,只有两个字段都是空都时候,才是nil interface{}

    var err error = (*errorDemo)(nil)
    猜猜 err ==nil 是true还是false,为什么?
    

    对于interface变量,一定要记住他的底层是两个部分组成的,值和method table,反射就是根据这个来进行的。

    发散

    golang中type 可以Embeded。拥有某个类型,那就拥有这个类型的一切(霸道总裁- -!)。有的时候,就会出现A类型没有实现某个接口,但是嵌入A中的B类型实现了,这个时候也相当于A实现了该接口。
    那么问题来了

    1. 如果A中还嵌入了C,C和B都实现了同样都接口I,那么会是什么情况?是调用C呢还是B呢还是别的?
    2. 如果A也实现了接口I呢?
    3. 根据1,2的理解,再考虑下,能不能实现重写,多态?
      可以留言,相互交流交流

    写的生疏,要睡觉了。读者可以再想想interface的转换(cast),这个比较常用

    延伸阅读

    http://go-book.appspot.com/interfaces.html

    原文 https://research.swtch.com/interfaces
    译文 http://shareinto.github.io/2016/03/08/GoDataStructures-Interfaces/interfaces.html

    参考文档

    1. Interface 结构: 这个是译文,原文很难打开 http://shareinto.github.io/2016/03/08/GoDataStructures-Interfaces/
      原文 https://research.swtch.com/interfaces
    2. golang io pkg
      https://golang.org/pkg/io/
    3. errors pkg
      https://github.com/pkg/errors

    相关文章

      网友评论

        本文标题:golang interface

        本文链接:https://www.haomeiwen.com/subject/zixnnttx.html