下面由golang教程欄目給大家介紹關(guān)于 golang 的接口,希望對(duì)需要的朋友有所幫助!
在Go語(yǔ)言中接口(interface)是一種類型,一種抽象的類型。
接口的定義
定義格式:
type 接口類型名 interface{ 方法名1( 參數(shù)列表1 ) 返回值列表1 方法名2( 參數(shù)列表2 ) 返回值列表2 … }
Go語(yǔ)言的接口在命名時(shí),一般會(huì)在單詞后面添加er,接口名最好要能突出該接口的類型含義。
接口實(shí)現(xiàn)
一個(gè)對(duì)象只要全部實(shí)現(xiàn)了接口中的方法,那么就實(shí)現(xiàn)了這個(gè)接口。
Go語(yǔ)言中不同的類型可以實(shí)現(xiàn)同一個(gè)接口。(示例中dog和cat都實(shí)現(xiàn)了Animal接口)
//定義一個(gè)Animal接口// Animal 是一個(gè)動(dòng)物接口,實(shí)現(xiàn)move()和say()方法type Animal interface { move() say() }//定義dog結(jié)構(gòu)體type dog struct { name string }//定義cat結(jié)構(gòu)體type cat struct { name string }//dog實(shí)現(xiàn)move方法func (d dog) move() { fmt.Printf("%s會(huì)跑n",d.name) }//dog實(shí)現(xiàn)say方法func (d dog) say() { fmt.Printf("%s會(huì)叫汪汪汪n",d.name) }//cat實(shí)現(xiàn)move方法func (c *cat) move() { fmt.Printf("%s會(huì)跑n",c.name) }//cat實(shí)現(xiàn)say方法func (c cat) say() { fmt.Printf("%s會(huì)叫喵喵喵n",c.name) }func main() { var a Animal //聲明一個(gè)Animal類型的a //實(shí)例化一個(gè)dog結(jié)構(gòu)體 d := dog{name:"旺財(cái)"} fmt.Printf("%Tn", d) //main.dog d.move() //旺財(cái)會(huì)跑 d.say() //旺財(cái)會(huì)叫汪汪汪 a = d // 接口是一種類型,一種抽象的類型。 fmt.Println(a) //{旺財(cái)} //實(shí)例化一個(gè)cat結(jié)構(gòu)體 c := cat{name:"藍(lán)貓"} c.move() //藍(lán)貓會(huì)跑 c.say() //藍(lán)貓會(huì)叫喵喵喵 }
多態(tài)
GO語(yǔ)言通過(guò)接口模擬多態(tài)。
類型與接口關(guān)系
一個(gè)類型可以同時(shí)實(shí)現(xiàn)多個(gè)接口,而接口間彼此獨(dú)立,不知道對(duì)方的實(shí)現(xiàn)。
Go語(yǔ)言中不同的類型可以實(shí)現(xiàn)同一個(gè)接口。
接口嵌套
接口與接口間可以通過(guò)嵌套創(chuàng)造出新的接口。
//定義speaker接口type speaker interface { speak() }//定義mover接口type mover interface { move() }// 接口嵌套type animal interface { speaker mover }//定義cat結(jié)構(gòu)體type cat struct { name string }//cat是值類型接收者func (c cat) speak() { fmt.Println("喵喵喵") }func (c cat) move() { fmt.Println("貓會(huì)動(dòng)") }func main() { var x animal x = cat{name: "花花"} x.move() //貓會(huì)動(dòng) x.speak() //喵喵喵 }
空接口
空接口定義
空接口是指沒(méi)有定義任何方法的接口。空接口類型的變量可以存儲(chǔ)任意類型的變量。
//空接口func main() { var x interface{} x = 100 //int類型 fmt.Println(x) //100 x = "ares" //string類型 fmt.Println(x) //ares x = struct { //結(jié)構(gòu)體類型 name string }{name:"ares"} //結(jié)構(gòu)體賦值 fmt.Println(x) //ares }
空接口應(yīng)用
空接口可以作為函數(shù)的參數(shù)或map的值。
//空接口func showType(a interface{}) { fmt.Printf("type:%Tn", a) }func main() { //空接口作為函數(shù)的參數(shù) showType(100) //type:int showType("ares") //type:string //定義一個(gè)值為空接口的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 { //如果要實(shí)現(xiàn)接口c,需要將接口a和接口b中的方法一起實(shí)現(xiàn) }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... }
類型斷言
語(yǔ)法:
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 %vn", v) case int: fmt.Printf("x is a int is %vn", v) case bool: fmt.Printf("x is a bool is %vn", v) case *string: fmt.Printf("x is a point指針 is %vn", v) case struct{}: fmt.Printf("x is a struct is %vn", 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! }
值接收者和指針接收者實(shí)現(xiàn)接口的區(qū)別
如果接收者為指針類型的話,不能把值傳進(jìn)去。
//定義animal接口type animal interface { speak() move() }//定義cat結(jié)構(gòu)體type cat struct{ name string }//定義dog結(jié)構(gòu)體type dog struct{ name string }//值接收者 func (c cat) speak() { fmt.Printf("%s會(huì)叫喵喵喵n",c.name) } func (c cat) move() { fmt.Printf("%s會(huì)動(dòng)n",c.name) } //指針接收者func (d *dog) speak() { fmt.Printf("%s會(huì)叫汪汪汪n",d.name) }func (d *dog) move() { fmt.Printf("%s會(huì)動(dòng)n",d.name) }func main() { var c1 animal lm := cat{name:"藍(lán)貓"} c1 = lm //因?yàn)閷?shí)現(xiàn)animal接口的是cat值類型,所以可以直接賦值 c1.move() //藍(lán)貓會(huì)動(dòng) c1.speak() //藍(lán)貓會(huì)叫喵喵喵 var c2 animal jm := &dog{name:"金毛"} //現(xiàn)animal接口的是*dog類型,所以必須要通過(guò)&來(lái)取值 c2 = jm c2.move() //金毛會(huì)動(dòng) c2.speak() //金毛會(huì)叫汪汪汪 }