Go 语言中的接口是一组方法的组合,它是 Go 语言的重要组成部分。简单的说,interface是一组method签名的组合,我们通过interface来定义对象的一组行为。interface 是一种类型,定义如下:
type Person interface {
Eat(food string)
}
它的定义可以看出来用了 type 关键字,更准确的说 interface 是一种具有一组方法的类型,这些方法定义了 interface 的行为。
golang
接口定义不能包含变量,但是允许不带任何方法,这种类型的接口叫 empty interface
。
如果一个类型实现了一个interface
中所有方法,我们就可以说该类型实现了该interface。
所以我们的所有类型都实现了empty interface
,因为任何一种类型至少实现了0个方法。并且go
中并不像java
中那样需要显式关键字来实现interface
,只需要实现interface
包含的方法即可。
在Go
语言中实现接口就是隐式的,只要实现了接口中的所有函数,即认为实现了接口。举例说明:
type error interface {
Error() string
}
type RPCError struct {
Code int64
Message string
}
func (e *RPCError) Error() string {
return fmt.Sprintf("%s, code=%d", e.Message, e.Code)
}
上面的代码,并没有error
接口的影子,我们只需要实现Error() string
方法就实现了error
接口。
在Go
中,实现接口的所有方法就隐式地实现了接口。我们使用上述 RPCError
结构体时并不关心它实现了哪些接口;Go 语言只会在传递参数、返回参数以及变量赋值时才会对某个类型是否实现接口进行检查。
Go
语言的这种写法很方便,不用引入包依赖。但是interface
底层实现的时候会动态检测也会引入一些问题:
package main
import "fmt"
type Reader interface {
Read() int
}
type MyStruct struct {
X, Y int
}
func (m *MyStruct) Read() int {
return m.X + m.Y
}
func run(r Reader) {
fmt.Println(r.Read())
}
func main() {
s := &MyStruct{3, 4}
run(s)
}
输出:
7
分析:
因为*MyStruct实现了Read方法,因此&MyStruct实现了Reader接口,所以把*MyStruct作为参数调用run时候,&MyStruct{3, 4}就自动实现了Reader接口,因此run里可以用r.Read()来调用接口的方法.
package main
import "fmt"
type Sumer interface {
Sum() int
}
type MyStruct struct {
X, Y int
}
func (this *MyStruct) Sum() int {
return this.X + this.Y
}
func New(a, b int) Sumer {
return &MyStruct{a, b}
}
func main() {
m := New(3, 4)
s := m.Sum()
fmt.Println(s)
}
输出
7
分析:
可以看出,因为*MyStruct实现了Sum方法,因此&MyStruct实现了Sumer接口;
import "fmt"
type Reader interface {
Read() int
}
type MyStruct struct {
X, Y int
}
func (m *MyStruct) Read() int {
return m.X + m.Y
}
func run(r interface{}) {
// 会报错
//fmt.Println(r.Read())
fmt.Println(r)
fmt.Printf("%T\n", r)
}
func main() {
s := &MyStruct{3, 4}
run(s)
}
输出
&{3 4}
*main.MyStruct
分析:
如果把上面例子中注释去掉,则会报错;
./example.go:19: r.Read undefined (type interface {} is interface with no methods)
https://segmentfault.com/a/1190000038552939
https://cyent.github.io/golang/method/interface_argv_interface/