跳到主要内容

go接口类型

go 接口定义了一组方法的签名(方法和函数的区别,参考go函数类型),它借鉴了 OOP 编程语言里 interface 的思想,但有一些不同。

1. 接口定义

go 里接口定义的语法如下:

type interface_name interface {

//method

}

 为了方便理解接口,以生活中的例子来说明:生活中常见的动物一般会跑会叫,可以定义一个动物接口,包含跑和叫两个方法签名。注意到,interface里面的 method 并没有func关键字。

type Animal interface {
run()
bark()
}

 接口可以用来声明变量,未初始化的接口类型变量值为nil,类型也为nil

var animal Animal
fmt.Println("value of animal", animal)
fmt.Printf("type of animal %T", animal)

2. 实现接口

go 没有提供 implements 这样的关键字来实现接口。只要某种类型包含了接口里定义的所有方法,即该类型实现了接口。下面例子定义了DogCat两种类型,并且都实现了runbark方法,这样DogCat都实现了Animal接口,那么 go 允许将DogCat赋值给Animal。使用Animal调用bark()run()方法时,实际上调用的是Dog或者Cat对应的方法,即实现了多态。

package main

import "fmt"

type Animal interface {
run()
bark()
}

type Dog struct {
name string
}

type Cat struct {
name string
}

func (cat *Cat) run() {
fmt.Println(cat.name + " likes run")
}

func (cat *Cat) bark() {
fmt.Println(cat.name + " likes bark")
}

func (dog *Dog) run() {
fmt.Println(dog.name + " is runing")
}

func (dog *Dog) bark() {
fmt.Println(dog.name + " is barking")
}

func main() {
var animal Animal = &Dog{
name: "my dog",
}
animal.bark()
animal.run()

animal = &Cat{
name: "mimi",
}

animal.bark()
animal.run()

}

3. 空接口

 如果一个接口没有定义任何方法,这个接口被称为空接口,空接口用interface{}表示。所有的类型都实现了空接口,例如:

package main

import "fmt"

func emptyInterface(i interface{}) {
fmt.Printf("\ntype of parameter is %T", i)
}

func main() {
emptyInterface(10)
emptyInterface("abc")
emptyInterface(10.5)
emptyInterface(struct{ string }{"hhh"})
}

4. 类型断言和类型转换

 前面例子中,DogCat都可以赋值给Animal这个接口,对于一个Animal类型的变量,实际的类型是Dog还是Cat呢?这个时候可以使用类型断言。下面例子里,假定iT类型,并将T类型的值赋给变量t,如果i的实际类型不为T(即断言失败),则会抛出异常。

t := i.(T)

 类型转换提供了更加便捷的类型断言,它的语法和switch类似。

switch v := i.(type) {
case T:
// here v has type T
case S:
// here v has type S
default:
// no match; here v has the same type as i
}

署名-非商业性使用-禁止演绎 4.0 国际