golang interface
这个是常见的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实现了该接口。
那么问题来了
- 如果A中还嵌入了C,C和B都实现了同样都接口I,那么会是什么情况?是调用C呢还是B呢还是别的?
- 如果A也实现了接口I呢?
- 根据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
参考文档
- Interface 结构: 这个是译文,原文很难打开 http://shareinto.github.io/2016/03/08/GoDataStructures-Interfaces/
原文 https://research.swtch.com/interfaces - golang io pkg
https://golang.org/pkg/io/ - errors pkg
https://github.com/pkg/errors