接口在Golang中表示一種抽象的數(shù)據(jù)類型锣杂,它用來(lái)定義對(duì)象的行為未玻,具體的實(shí)現(xiàn)由對(duì)象決定。程序編寫(xiě)時(shí)如果僅僅定義接口是沒(méi)有實(shí)際意義的颅和,我們需要自定義類型,如果類型對(duì)某個(gè)接口的所有方法提供了定義缕允,就說(shuō)這個(gè)類型實(shí)現(xiàn)了該接口峡扩。
-
定義接口
Golang中接口的定義使用interface關(guān)鍵字,后面緊跟一個(gè)大括號(hào)障本,里面包含若干函數(shù)(參數(shù)和返回值不是必需的)教届,比如,
type People interface {
GetName() string // 帶有返回值的方法
GetAge(id int) // 帶有參數(shù)的方法
GetTelephone(a int) int //同時(shí)帶有參數(shù)和返回值的方法
}
一個(gè)接口是方法集的藍(lán)圖驾霜,在使用前必須有類型實(shí)現(xiàn)它案训,如果不能滿足這個(gè)條件,接口是不能使用的粪糙。
-
定義一個(gè)實(shí)現(xiàn)接口的類型
下面定義一個(gè)帶有兩個(gè)方法的接口:People强霎,然后定義一個(gè)類型:Ple,該類型擁有People中聲明的方法(注意:這里方法的參數(shù)和返回值都要和接口People中的方法保持一致)
package main
import "fmt"
type People interface {
GetName(name string)
GetAge(a int) int
}
type Ple struct {
}
func (p Ple) GetName(name string) {
fmt.Println("People Name:\t", name)
}
func (p Ple) GetAge(a int) int {
return a
}
func main() {
var p1 People
p1 = Ple{}
p1.GetName("John Doe")
fmt.Println("Ple Age:", p1.GetAge(25))
}
上面代碼中Ple類型實(shí)現(xiàn)了接口People聲明的所有方法蓉冈,此時(shí)城舞,就可以將Ple的實(shí)例賦值給People的變量p1。
-
定義滿足多個(gè)接口的類型
用戶自定義類型可以同時(shí)滿足多個(gè)接口寞酿,使用“類型斷言”(即Type Assertion)可以得到實(shí)際的自定義類型家夺,通過(guò)該類型調(diào)用接口未包含的方法:
package main
import "fmt"
type People interface {
GetName()
}
type Animal interface {
GetAge()
}
type Custom struct
}
func (c Custom) GetName() {
fmt.Println("name is xiaoli")
}
func (c Custom) GetAge() {
fmt.Println("age is 5")
}
func main() {
var p People = Custom{}
p.GetName()
p.GetAge()
var o Custom = p.(Custom)
o.GetAge()
}
將“Custom”類型的實(shí)例賦值給接口變量p,可以直接通過(guò)接口變量p調(diào)用方法“GetName”伐弹,但是不能直接調(diào)用方法“GetAge”拉馋,因?yàn)榻涌凇癙eople”沒(méi)有方法“GetAge”,這時(shí)使用類型斷言得到實(shí)際的自定義類型值惨好,就可以調(diào)用接口“People”本不具有的方法“GetAge”煌茴。(上面代碼的最后兩行可以直接寫(xiě)成“p.(Custom).GetAge()”)
- 接口接收變量的地址
package main
import "fmt"
type Student struct {
name,address string
}
func (s *Student) Init (n,d string) {
s.name = n
s.address = d
}
func (s *Student) Print () {
fmt.Printf("Student name is %s,address is %s \n",s.name,s.address)
}
type Printer interface {
Print()
}
func main() {
var s Student
s.Init("xiaoli","shenzhen")
var p Printer
p = &s //賦值地址類型
p.Print()
}
因?yàn)镻rinter方法有指針接收者:“func (s *Student) Print ()”,所以給接口變量賦值時(shí)昧狮,必須使用變量地址:“p = &s”景馁,如果不符合,會(huì)有如下報(bào)錯(cuò):
# command-line-arguments
./interface-test.go:26:4: cannot use s (type Student) as type Printer in assignment:
Student does not implement Printer (Print method has pointer receiver)
-
空接口類型
類型“interface{}”稱之為空接口逗鸣,因?yàn)榭战涌陬愋蜎](méi)有定義任何方法合住,所以任何類型都可以認(rèn)為實(shí)現(xiàn)了該接口绰精,當(dāng)一個(gè)函數(shù)不在乎參數(shù)類型時(shí),可以指定參數(shù)類型為“interface{}”