开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
接口类型
Go语言中的接口interface是一种抽象的类型,也可以称作多种方法的集合,这些方法是作用在某个数据类型上的,会有个接受者来表名当前方法是作用在哪个数据上,接口是用来定义一套标准,不关心属性数据,只关心行为。
type Cat struct{}
func (c Cat) Say() string { return "喵" }
type Dog struct{}
func (d Dog) Say() string { return "汪" }
func main() {
c := Cat{}
fmt.Println("猫:", c.Say())
d := Dog{}
fmt.Println("狗:", d.Say())
}
上面的代码中定义了猫和狗,然后它们都会叫,上面代码中有重复的地方。
为了解决这种问题,把共性的东西抽象出来,那么接口是一种抽象的类型,当你看到一个接口类型的值时,你不知道它是什么,唯一知道的是通过它的方法能做什么。
接口的定义
- 接口是一个或多个方法签名的集合
- 任何类型的方法集中只要拥有该接口对应的全部方法签名
- 就表示它 实现了该接口,无须在该类型上显式声明实现了哪个接口
- 所谓对应方法,是指有相同名称、参数列表 (不包括参数名) 以及返回值
- 接口只有方法声明,没有具体实现,没有数据字段
- 接口可以匿名嵌入其他接口
- 一个类型可以实现多个接口
接口的定义如下所示:
type 接口类型名 interface{
方法名1( 参数列表1 ) 返回值列表1
方法名2( 参数列表2 ) 返回值列表2
…
}
- 接口名:使用type将接口定义为自定义的类型名,最后在后面加上er,如有读操作的接口叫Reader,有字符串功能的接口叫Stringer等,接口的名字最好能直接表达其作用
- 方法名:当方法名首字母是大写且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问
- 参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以省略
值接收者、指针接收者实现接口
值接收者
func (d dog) move() {
fmt.Println("狗会动")
}
func main() {
var x Mover
var beila = dog{} // 贝拉是dog类型
x = beila // x可以接收dog类型
x.move()
var duoduo = &dog{} // 多多是*dog类型
x = duoduo // x可以接收*dog类型
x.move()
}
观察上述代码可以知道,使用值接收者实现接口之后,不管是普通结构体还是结构体指针*dog类型的变量都可以赋值给该接口变量,因为Go语言本身对指针会进行自动求值。
指针接收者
func (d *dog) move() {
fmt.Println("狗会动")
}
func main() {
var x Mover
var beila = dog{} // 贝拉是dog类型
x = beila // x不可以接收dog类型
x.move()
var duoduo = &dog{} // 多多是*dog类型
x = duoduo // x可以接收*dog类型
x.move()
}
这里Mover接口实现的是*dog类型,所以不能给x传入dog类型的beila,此时x只能存储*dog类型的值
空接口的应用、断言
空接口
空接口是指没有定义任何方法的接口,这就意味着任何类型都实现了空接口
空接口类型的变量可以存储任意类型的变量,空接口可以实现保存任意值的字典
// 空接口作为map值
var studentInfo = make(map[string]interface{})
studentInfo["name"] = "张三"
studentInfo["age"] = 20
studentInfo["married"] = false
fmt.Println(studentInfo)
断言
判断空接口中的值:使用类型断言,其语法格式:
x.(T) :
返回第一个参数是x转化为T类型后的变量
返回第二参数是一个布尔值,若为true则表示断言成功,为false则表示断言失败。
x:表示类型为interface{}的变量
T:表示断言x可能是的类型。
断言多次可以使用switch来实现
func testType(x interface{}) {
switch v := x.(type) {
case string:
fmt.Printf("x is a string,value is %v\n", v)
case int:
fmt.Printf("x is a int is %v\n", v)
case bool:
fmt.Printf("x is a bool is %v\n", v)
default:
fmt.Println("unsupport type!")
}
}
总结
今天主要学习了Go的接口定义,如何区分值接收者和指针接收者,又或者是空接口的应用和类型断言,这都是后面需要反复复习的,对于刚入门go语言的我来说,还有许多地方需要学习,有错误的地方欢迎大家指出,共同进步!!