接口是双方约定的一种合作协议。接口实现者不需要关心接口会被怎样使用,调用者也不需要关心接口的实现细节。
接口是一种类型,也是一种抽象结构,不会暴露所含数据的格式、类型及结构。
声明:
接口类型是由一组方法签名定义的集合
type 接口类型名 interface{
方法名1( 参数列表1 ) 返回值列表1
方法名2( 参数列表2 ) 返回值列表2
…
}
type Goer interface {write() (int,error)Read() error }
var 接口名 接口类型名
var goer Goer
接口本身包含两个数据(值,类型),只有当两者都是nil时才为接口值才为nil
实现:
接口类型的变量可以保存任何实现了这些方法的值。
要求:
接口的方法与实现接口的类型方法格式一致
接口中所有方法均被实现
type Goer interface {write() float64 } func main() {var goer Goerv := Vertex{ 3, 4}f := MyFloat(-3.14)//goer=v //编译错误,没有v Vertex的对应方法goer = &vfmt.Println(goer.write())goer = ffmt.Println(goer.write()) } type MyFloat float64 func (f MyFloat) write() float64 {if f < 0 {return float64(-f)}return float64(f) } type Vertex struct {X, Y float64 } func (v *Vertex) write() float64 {return math.Sqrt(v.X*v.X + v.Y*v.Y) }
运行结果:
5
3.14
类型和接口之间有一对多和多对一的关系,一个类型可以同时实现多个接口,而接口间彼此独立,不知道对方的实现,同时一个接口的方法,不一定需要由一个类型完全实现,接口的方法可以通过在类型中嵌入其他类型或者结构体来实现
空接口:
指定了零个方法的接口值被称为空接口
由于每个类型的方法都至少实现了0种,所以不用指定方法,可以用来保存任何类型的值或者处理未知类型的值
interface{}
var a interface{}
例子:
func main() {var i interface{}describe(i) i = 42describe(i) i = "hello"describe(i) } func describe(i interface{}) {fmt.Printf("(%v, %T) ", i, i) }
输出结果:
(
(42, int)
(hello, string)
函数接口:
除了结构体和类型能实现接口,函数类型也可以实现接口
// 调用器接口 type Invoker interface {// 需要实现一个Call方法Call(interface{}) } // 函数定义为类型 type FuncCaller func(interface{}) // 实现Invoker的Call func (f FuncCaller) Call(p interface{}) {// 调用f函数本体 f(p) } func main() {// 声明接口变量var invoker Invoker// 将匿名函数转为FuncCaller类型,再赋值给接口invoker = FuncCaller(func(v interface{}) {fmt.Println("from function", v)})// 使用接口调用FuncCaller.Call,内部会调用函数本体invoker.Call("hello") }
运行结果:
from function hello