32 Go 語(yǔ)言中的接口
在所有編程語(yǔ)言中,接口都是一些方法的集合,通常都是"類"們都需要實(shí)現(xiàn)的一些公共方法。使這些"類"在使用過(guò)程中多了一層抽象。在使用接口時(shí)無(wú)需在意這些方法是如何實(shí)現(xiàn)的,只需在意這個(gè)接口中的方法本身。Go 語(yǔ)言提倡面向接口編程,一來(lái)增強(qiáng)代碼的可讀性,二來(lái)可以使代碼的模塊之間的關(guān)系變得更加清晰、邊界更加明顯。本文就來(lái)介紹一下 Go 語(yǔ)言中的接口。
1. 接口定義
在 Go 語(yǔ)言中,接口也是一個(gè)數(shù)據(jù)類型,該類型使用結(jié)構(gòu) interface{...}
來(lái)定義。
代碼示例:
var stuInterface interface{
PrintAge()
}
以上代碼定義可一個(gè)接口類型的變量,其中包含的方法為 PrintAge()。
2. 接口實(shí)現(xiàn)
了解了 Go 語(yǔ)言中接口的定義之后,我們來(lái)學(xué)習(xí)一下如何實(shí)現(xiàn)Go語(yǔ)言的接口。
在 Go 語(yǔ)言的接口中有兩個(gè)非常重要的特性:
- 只要有類實(shí)現(xiàn)(模擬)了接口中包含的所有方法,我們就稱這個(gè)類型實(shí)現(xiàn)了這個(gè)接口;
- 只要是實(shí)現(xiàn)了這個(gè)接口的類型,用這個(gè)類型定義的變量就可以給這個(gè)接口聲明的變量賦值。
所以從以上兩個(gè)特性也可以推出 interface{} 類型的變量,可以接收 任何變量的賦值。這兩個(gè)特性也被稱為鴨子類型,即"走起來(lái)像鴨子,叫起來(lái)像鴨子(類型模擬了接口中包含的所有方法),那么它就是一只鴨子"。
代碼示例:
package main
import (
"fmt"
)
var stuInterface interface {
PrintAge()
}
type Student struct {
Name string
Age int
}
func (s Student) PrintAge() {
fmt.Println(s.Age)
}
func main() {
stuInterface = Student{
Name: "Codey",
Age: 18,
}
stuInterface.PrintAge()
}
- 第 21~24 行:定義了一個(gè)自定義類型,并且這個(gè)類型實(shí)現(xiàn)了接口變量類型中的方法;
- 第 21 行:實(shí)例化一個(gè)自定義類型的變量,并賦值給這個(gè)接口變量;
- 第 25 行:使用接口中的方法。會(huì)發(fā)現(xiàn)打印了學(xué)生的年齡。
執(zhí)行結(jié)果:
3. 自定義接口類型
為了方便使用,一般都會(huì)使用自定義類型來(lái)定義一個(gè)接口類型。同時(shí)還可以寫一個(gè)函數(shù)來(lái)實(shí)例化接口。
代碼示例:
package main
import (
"fmt"
)
type StudentInterface interface {
PrintAge()
}
type Student struct {
Name string
Age int
}
func (s Student) PrintAge() {
fmt.Println(s.Age)
}
func newStudent(name string, age int) StudentInterface {
return Student{Name: name, Age: age}
}
func main() {
stuInterface := newStudent("Codey", 18)
stuInterface.PrintAge()
}
- 第 20~22 行:定義一個(gè)函數(shù)來(lái)實(shí)例化接口;
- 第 24 行:初始化一個(gè)接口變量。
執(zhí)行結(jié)果:
4. 小結(jié)
本文主要介紹了 Go 語(yǔ)言中接口的定義和使用。需要注意以下幾點(diǎn):
- 在 Go 語(yǔ)言中接口是一個(gè)類型;
- 一般使用自定義類型來(lái)定義接口;
- Go 語(yǔ)言的接口是鴨子類型。