如何使用 Go interface
前言
记录自己对 Go interface的理解与应用。
interface的定义
- interface是一组方法的集合,任何类型只要实现了 interface 中方法集合,那么就属于这个类型;
- Go interface使用的是一种鸭子类型的方式让动态类型成为了可能;
假设定义一个 Engine 接口:
package main
import "fmt"
// 定义Engine接口
type Engine interface {
Start()
Stop()
}
type Car struct{}
type Airplane struct{}
// Car的实现,c接收者接收了Start方法
func (c Car) Start() {
fmt.Println("Car is running.")
}
func (c Car) Stop() {
fmt.Println("Car stop.")
}
func (a Airplane) Start() {
fmt.Println("Airplane is running.")
}
func (a Airplane) Stop() {
fmt.Println("Airplane stop.")
}
func startEngine(e Engine) {
e.Start()
}
func stopEngine(e Engine) {
e.Stop()
}
func main() {
var car Car
var airplane Airplane
startEngine(car) // Car is running.
startEngine(airplane) // Airplane is running.
stopEngine(car) // Car stop.
stopEngine(airplane) // Airplane stop.
}
interface应用
interface{}它不是泛型,它是一个接口,这个接口可以适配任何类型;
nil interface
- nil interface的官方解释:Interface values with nil underlying values;
- 只声明没赋值的interface 是 nil interface,value 和 type 都是 nil;
- 只要赋值了,即使赋了一个值为 nil 类型,也不再是 nil interface;
package main
import "fmt"
type I interface {
M()
}
type T struct {
S string
}
func (t *T) M() {
if t == nil {
fmt.Println("<nil>")
return
}
fmt.Println(t.S)
}
func describe(i I) {
fmt.Printf("(%v, %T)\n", i, i)
}
func main() {
var i I
var t *T
i = t
describe(t)
i.M()
i = &T{"hello"}
describe(i)
i.M()
}
output
(<nil>, *main.T)
<nil>
(&{hello}, *main.T)
hello
empty interface 空接口
interface{}叫做空接口,空接口表示包含了0个方法的集合,由于任何类型都至少实现了0个方法,所以空接口可以承接任意类型;
- 空接口不用指定类型变量,并且类型可变:
package main
import "fmt"
type I interface{}
func main() {
var i I
i = 42 //这个时候i就是int类型
fmt.Printf("%v,%T\n", i, i)
i = "hello" //这个时候i就是string类型
fmt.Printf("%v,%T\n", i, i)
}
output
42,int
hello,string
struct 中嵌套 interface
struct中嵌套interface,这种情况比较特殊,struct中嵌套interface之后,struct会自动获得接口规定的方法:
package main
import "fmt"
type I interface {
M()
}
type T struct {
I
}
type K struct {
s string
}
func (k *K) M() {
fmt.Println(k.s)
}
func newT(s string) *T {
return &T{&K{s}}
}
func main() {
t := newT("Hello")
t.M()
}
output
hello