Go语言的接口并不是其他语言(C++、Java、C#等)中所提供的接口概念。
基于模块设计的单向依赖原则,模块A在实现自身的业务时,不应该关心某个具体使用方的要求。模版A实现的时候,甚至不知道会有如今B来使用它。
非侵入式接口
在Go语言中,一个类只需要实现了接口要求的所有函数,我们就说这个类实现了该接口。
type File struct { // ... } func (f *File) Read(buf []byte) (n int, err error) func (f *File) Write(buf []byte) (n int, err error) func (f *File) Seek(off int64, whence int) (pos int64, err error) func (f *File) Close() errorFile类实现了4个方法
如有接口:
type IFile interface { Read(buf []byte) (n int, err error) Write(buf []byte) (n int, err error) Seek(off int64, whence int) (pos int64, err error) Close() error }
type IReader interface { Read(buf []byte) (n int, err error) } type IWriter interface { Write(buf []byte) (n int, err error) } type ICloser interface { Close() error }尽管File类并没有从这些接口继承,甚至可以不知道这些接口的存在,但是File类实现了这些接口,可以进行赋值:
var file1 IFile = new(File) var file2 IReader = new(File) var file3 IWriter = new(File) var file4 ICloser = new(File)因为File类实现 接口 要求的 所有方法
接口赋值
接口赋值在Go语言中分为如下两种情况:- 将对象实例赋值给接口;
- 将一个接口赋值给另一个接口。
type Integer int <pre name="code" class="plain">func (a Integer) Less(b Integer) bool { return a < b }func (a *Integer) Add(b Integer) { *a += b} 定义接口
type LessAdder interface { Less(b Integer) bool Add(b Integer) }
var a Integer = 1 var b LessAdder = &a ... (1)ok <span style="font-family: Arial, Helvetica, sans-serif;"> </span>var b LessAdder = a ... (2)no
</pre><pre name="code" class="plain">GO可以根据 func (a Integer) Less(b Integer) bool 自动生成新方法 func (a *Integer) Less(b Integer) bool { return (*a).Less(b) }接口赋值并不要求两个接口必须等价。如果接口A的方法列表是接口B的方法列表的子集,那么接口B可以赋值给接口A。
接口查询
var file1 Writer = ... if file5, ok := file1.(two.IStream); ok { ... }这个if语句检查file1接口指向的对象实例是否实现了two.IStream接口。
在Go语言中,你可以询问接口它指向的对象是否是某个类型,比如:
var file1 Writer = ... if file6, ok := file1.(*File); ok { //这个if语句判断file1接口指向的对象实例是否是*File类型 ... }
类型查询
在Go语言中,还可以更加直截了当地询问接口指向的对象实例的类型,例如:var v1 interface{} = ... switch v := v1.(type) { case int: // 现在v的类型是int case string: // 现在v的类型是string ... }
接口组合
//接口中可以组合其它接口,这种方式等效于在接口中添加其它接口的方法 type Reader interface { read() } type Writer interface { write() } //定义上述两个接口的实现类 type MyReadWrite struct{} func (mrw *MyReadWrite) read() { fmt.Println("MyReadWrite...read") } func (mrw *MyReadWrite) write() { fmt.Println("MyReadWrite...write") } //定义一个接口,组合了上述两个接口 type ReadWriter interface { Reader Writer } //上述接口等价于: type ReadWriterV2 interface { read() write() } //ReadWriter和ReadWriterV2两个接口是等效的,因此可以相互赋值 func interfaceTest0104() { mrw := &MyReadWrite{} //mrw对象实现了read()方法和write()方法,因此可以赋值给ReadWriter和ReadWriterV2 var rw1 ReadWriter = mrw rw1.read() rw1.write() fmt.Println("------") var rw2 ReadWriterV2 = mrw rw2.read() rw2.write() //同时,ReadWriter和ReadWriterV2两个接口对象可以相互赋值 rw1 = rw2 rw2 = rw1 }
Any类型
由于Go语言中任何对象实例都满足空接口interface{},所以interface{}看起来像是可以指向任何对象的Any类型,如下:var v1 interface{} = 1 // 将int类型赋值给interface{} var v2 interface{} = "abc" // 将string类型赋值给interface{} var v3 interface{} = &v2 // 将*interface{}类型赋值给interface{} var v4 interface{} = struct{ X int }{1} var v5 interface{} = &struct{ X int }{1}
有疑问加站长微信联系(非本文作者)