基本介绍
- Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
- 接口可以让我们将不同的类型绑定到一组公共的方法上,从而实现多态和灵活的设计。
- Go 语言中的接口是隐式实现的,也就是说,如果一个类型实现了一个接口定义的所有方法,那么它就自动地实现了该接口。
- 一个类型可以实现多个接口,一个接口也可以被多个类型实现。
基本使用
type Animal interface {
Run()
Say()
}
type Horse struct {
Name string
}
type Dog struct {
Name string
}
func (h *Horse) Run(){
fmt.Println("Horse Run")
}
func (h *Horse) Say(){
fmt.Println("Horse Say")
}
func (d *Dog) Run(){
fmt.Println("Dog Run")
}
func (d *Dog) Say(){
fmt.Println("Dog Say")
}
func animalAction(animal Animal){
animal.Run()
animal.Say()
}
func main(){
horse := &Horse{
"Horse",
}
dog := &Dog{
"dog",
}
fish := &Fish{
"fish",
}
animalAction(horse) // Horse Run Horse Say
animalAction(dog)// Dog Run Dog Say
}
代码解释
- 我们先定义了一个动物的接口,接口有两个方法签名
- 定义了马的结构体,并实现了接口的两个方法,所以这个马的结构体实现了动物接口
- 定义了狗的结构体,并实现了接口的两个方法,所以这个狗的结构体实现了动物接口
- 定义一个 animalAction 函数,参数是 接口类型,意味着只要实现了该接口的类型都可以传
- 在 main 函数中,分别实例化了一个马和一个狗并传入 animalAction ,从而实现了多态
空接口 interface{}
- 空接口是指没有定义任何方法的接口。
- 因此任何类型都实现了空接口。
- 空接口类型的变量可以存储任意类型的变量。
- 使用空接口实现可以接收任意类型的函数参数。
- 把一个空接口类型的值赋值给一个类型需要通过断言。
类型断言
我们可以通过变量后面 . (类型)的语法对变量进行断言
func demo1(){
var i interface{}
var str string
i = "adf"
str = i.(string)
fmt.Print(str) // abc
}
func demo2(){
var i interface{}
var number int
i = 123
number = i.(int)
fmt.Print(number) // 123
}
函数传参
- 可以把接口类型的数据传入到函数里。
- 想知道断言是否成功可以通过接口第二个参数。
func demo3(i interface{}){
value1 ,ok1 := i.(string)
if ok1 {
fmt.Printf("i is string,value:%s\n",value1)
}
value2 ,ok2 := i.(int)
if ok2 {
fmt.Printf("i is int,value:%d\n",value2)
}
}
func main(){
demo3(1) // i is int,value:1
demo3("abc") // i is string,value:abc
}
switch 判断类型
如果觉得上面那种 if 判断多个类型的时候很麻烦,我们可以使用 switch i.(type) 语法来判断多个类型。
func demo4(i interface{}){
switch i.(type) {
case int:
fmt.Println("is int")
case string:
fmt.Println("is string")
case bool:
fmt.Println("is bool")
}
}
func main(){
demo4(1)//is int
demo4("abc")// is string
demo4(true)//is bool
}