Golang接口类型-上篇
介绍 Go 接口的基本概念、隐式实现、类型赋值及实际应用。

概述
接口是计算机系统中多个组件共享的边界,不同的组件能够在边界上交换信息。接口的本质是引入一个新的中间层,调用方可以通过接口与具体实现分离,解除上下游的耦合,上层的模块不再需要依赖下层的具体模块,只需要依赖一个约定好的接口
简单来说,Go语言中的接口就是一组方法的签名。接口是Go语言整个类型系统的基石,其他语言的接口是不同组件之间的契约的存在,对契约的实现是强制性的,必须显式声明实现了该接口,这类接口称之为“侵入式接口”。而Go语言的接口是隐式存在,只要实现了该接口的所有函数则代表已经实现了该接口,并不需要显式的接口声明
接口的比喻
一个常见的例子,电脑上只有一个USB接口。这个USB接口可以接MP3、数码相机、摄像头、鼠标、键盘等。所有的上述硬件都可以公用这个接口,有很好的扩展性,该USB接口定义了一种规范,只要实现了该规范,就可以将不同的设备接入电脑,而设备的改变并不会对电脑本身有什么影响(低耦合)
接口表示调用者和设计者的一种约定,在多人合作开发同一个项目时,事先定义好相互调用的接口可以大大提高开发的效率。接口是用类来实现的,实现接口的类必须严格按照接口的声明来 实现接口提供的所有功能。有了接口,就可以在不影响现有接口声明的情况下,修改接口的内部实现,从而使兼容性问题最小化
接口的隐式实现
在Java中实现接口需要显式地声明接口并实现所有方法,而在Go中实现接口的所有方法就隐式地实现了接口
定义接口需要使用interface关键字,在接口中只能定义方法签名,不能包含成员变量,例如
type error interface {
Error() string
}
如果一个类型需要实现error接口,那么它只需要实现Error() string方法,下面的RPCError结构体就是 error 接口的一个实现
type RPCError struct {
Code int64
Message string
}
func (e *RPCError) Error() string {
return fmt.Sprintf("%s, code=%d", e.Message, e.Code)
}
会发现上述代码根本就没有error接口的影子,这正是因为Go语言中接口的实现都是隐式的
接口定义和声明
接口是自定义类型,是对其他类型行为的抽象(定义一个接口类型,把其他类型的值赋值给自定义的接口)
接口定义使用interface标识,声明了一系列的函数签名(函数名、函数参数、函数返回值)在定义接口时可以指定接口名称,在后续声明接口变量时使用
声明接口变量只需要定义变量类型为接口名,此时变量被初始化为nil
package main
import "fmt"
type Sender interface {
Send(to string, msg string) error
SendAll(tos []string, msg string) error
}
func main() {
var sender Sender
fmt.Printf("%T %v\n", sender, sender) // <nil> <nil>
}