从零开始学Go之接口(一):接口

接口是双方约定的一种合作协议。接口实现者不需要关心接口会被怎样使用,调用者也不需要关心接口的实现细节。

接口是一种类型,也是一种抽象结构,不会暴露所含数据的格式、类型及结构。

 

声明:

接口类型是由一组方法签名定义的集合

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 Goer
 v := Vertex{3, 4}
 f := MyFloat(-3.14)
 //goer=v //编译错误,没有v Vertex的对应方法
 goer = &v
 fmt.Println(goer.write())
 goer = f
 fmt.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 = 42
 describe(i)
​
 i = "hello"
 describe(i)
}
​
func describe(i interface{}) {
 fmt.Printf("(%v, %T)\n", i, i)
}

输出结果:

(<nil>, <nil>)

(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

posted @ 2019-07-02 12:30  VingB2by  阅读(183)  评论(0编辑  收藏  举报