接口介紹
在Go語言中接口(interface)是一種類型,一種抽象的類型。
接口的定義
定義格式:
type 接口類型名 interface{
方法名1( 參數列表1 ) 返回值列表1
方法名2( 參數列表2 ) 返回值列表2
…
}
Go語言的接口在命名時,一般會在單詞后面添加er,接口名最好要能突出該接口的類型含義。
接口實現
一個對象只要全部實現了接口中的方法,那么就實現了這個接口。
Go語言中不同的類型可以實現同一個接口。(示例中dog和cat都實現了Animal接口)
//定義一個Animal接口
// Animal 是一個動物接口,實現move()和say()方法
type Animal interface {
move()
say()
}
//定義dog結構體
type dog struct {
name string
}
//定義cat結構體
type cat struct {
name string
}
//dog實現move方法
func (d dog) move() {
fmt.Printf("%s會跑\n",d.name)
}
//dog實現say方法
func (d dog) say() {
fmt.Printf("%s會叫汪汪汪\n",d.name)
}
//cat實現move方法
func (c *cat) move() {
fmt.Printf("%s會跑\n",c.name)
}
//cat實現say方法
func (c cat) say() {
fmt.Printf("%s會叫喵喵喵\n",c.name)
}
func main() {
var a Animal //聲明一個Animal類型的a
//實例化一個dog結構體
d := dog{name:"旺財"}
fmt.Printf("%T\n", d) //main.dog
d.move() //旺財會跑
d.say() //旺財會叫汪汪汪
a = d // 接口是一種類型,一種抽象的類型。
fmt.Println(a) //{旺財}
//實例化一個cat結構體
c := cat{name:"藍貓"}
c.move() //藍貓會跑
c.say() //藍貓會叫喵喵喵
}
多態
GO語言通過接口模擬多態。
類型與接口關系
一個類型可以同時實現多個接口,而接口間彼此獨立,不知道對方的實現。
Go語言中不同的類型可以實現同一個接口。
接口嵌套
接口與接口間可以通過嵌套創造出新的接口。
//定義speaker接口
type speaker interface {
speak()
}
//定義mover接口
type mover interface {
move()
}
// 接口嵌套
type animal interface {
speaker
mover
}
//定義cat結構體
type cat struct {
name string
}
//cat是值類型接收者
func (c cat) speak() {
fmt.Println("喵喵喵")
}
func (c cat) move() {
fmt.Println("貓會動")
}
func main() {
var x animal
x = cat{name: "花花"}
x.move() //貓會動
x.speak() //喵喵喵
}
空接口
空接口定義
空接口是指沒有定義任何方法的接口。空接口類型的變量可以存儲任意類型的變量。
//空接口
func main() {
var x interface{}
x = 100 //int類型
fmt.Println(x) //100
x = "ares" //string類型
fmt.Println(x) //ares
x = struct { //結構體類型
name string
}{name:"ares"}
fmt.Println(x) //ares
}
空接口應用
空接口可以作為函數的參數或map的值。
//空接口
func showType(a interface{}) {
fmt.Printf("type:%T\n", a)
}
func main() {
//空接口作為函數的參數
showType(100) //type:int
showType("ares") //type:string
//定義一個值為空接口的map
var stu = make(map[string]interface{},100)
stu["ares"] = 100
stu["ares1"] = "男"
fmt.Println(stu) //map[ares:100 ares1:男]
//map,key是字符串,value是任意類型
map1 := make(map[string]interface{})
map1["name"] = "ares"
map1["age"] = 18
map1["id"] = 1
map1["friend"] = struct {
name string
age int
}{"jay", 33}
fmt.Println(map1) //map[age:18 friend:{jay 33} id:1 name:ares]
}
接口嵌套
類似於繼承。
type A interface {
test1()
}
type B interface {
test2()
}
type C interface {
A
B
test3()
}
type Cat struct { //如果要實現接口c,需要將接口a和接口b中的方法一起實現
}
func (c Cat) test1() {
fmt.Println("test1...")
}
func (c Cat) test2() {
fmt.Println("test2...")
}
func (c Cat) test3() {
fmt.Println("test3...")
}
func main() {
var cat = Cat{}
cat.test1() //test1...
cat.test2() //test2...
cat.test3() //test3...
//將cat賦值接口A類型,則只能使用test1方法
var cat1 A = Cat{}
cat1.test1() //test1...
//將cat賦值接口B類型,則只能使用test2方法
var cat2 B = Cat{}
cat2.test2() //test2...
}
類型斷言
語法:
x.(T)
x:表示類型為interface{}的變量
T:表示斷言x可能是的類型
若為true則表示斷言成功,為false則表示斷言失敗。
//類型斷言
func justifyType(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)
case *string:
fmt.Printf("x is a point指針 is %v\n", v)
case struct{}:
fmt.Printf("x is a struct is %v\n", v)
default:
fmt.Println("unsupport type!")
}
}
func main() {
justifyType(100) //x is a int is 100
justifyType("ares") //x is a string,value is ares
justifyType(false) //x is a bool is false
x := "ares"
justifyType(&x) //x is a point指針 is 0xc000094010
justifyType(struct {}{}) //x is a struct is {}
justifyType([]int{123}) //unsupport type!
}
值接收者和指針接收者實現接口的區別
如果接收者為指針類型的話,不能把值傳進去。
//定義animal接口
type animal interface {
speak()
move()
}
//定義cat結構體
type cat struct{
name string
}
//定義dog結構體
type dog struct{
name string
}
//值接收者
func (c cat) speak() {
fmt.Printf("%s會叫喵喵喵\n",c.name)
}
func (c cat) move() {
fmt.Printf("%s會動\n",c.name)
}
//指針接收者
func (d *dog) speak() {
fmt.Printf("%s會叫汪汪汪\n",d.name)
}
func (d *dog) move() {
fmt.Printf("%s會動\n",d.name)
}
func main() {
var c1 animal
lm := cat{name:"藍貓"}
c1 = lm //因為實現animal接口的是cat值類型,所以可以直接賦值
c1.move() //藍貓會動
c1.speak() //藍貓會叫喵喵喵
var c2 animal
jm := &dog{name:"金毛"} //現animal接口的是*dog類型,所以必須要通過&來取值
c2 = jm
c2.move() //金毛會動
c2.speak() //金毛會叫汪汪汪
}