基本介紹
接口是一個資料類型,可以定義一組方法,但都不需要實作。并且interface中不能包含任何變量。到某個自定義類型要使用的時候,再根據具體情況把這些方法實作出來
文法
type 接口名 interface {
method1(參數清單) 傳回值清單
method2(參數清單) 傳回值清單
}
說明:
- 接口申明中所有的方法,都沒有方法體,即接口中的方法都是沒有實作的方法。接口展現了程式設計的多态和高内聚低耦合的思想
- golang中的接口不需要顯式的實作,隻要一個變量含有接口類型中的所有方法,那麼這個變量就實作了這個接口
入門示例
package main
import "fmt"
// 聲明一個Usb接口
type Usb interface {
Start()
Stop()
}
// 定義一個手機結構體
type Phone struct {
}
// 手機結構體實作接口方法
func (p Phone) Start() {
fmt.Println("手機開始工作...")
}
func (p Phone) Stop() {
fmt.Println("手機停止工作...")
}
// 定義一個相機結構體
type Camera struct {
}
// 相機結構體實作接口方法
func (c Camera) Start() {
fmt.Println("相機開始工作...")
}
func (c Camera) Stop() {
fmt.Println("相機停止工作...")
}
// 定義一個電腦結構體
type Computer struct{}
// 電腦結構體綁定方法,接受Usb接口參數
func (c Computer) Working(usb Usb) {
usb.Start()
usb.Stop()
}
func main() {
phone := Phone{}
camera := Camera{}
computer := Computer{}
computer.Working(phone)
computer.Working(camera)
}
接口細節
- 接口本身不能建立執行個體,但是可以指向一個實作了該接口的自定義類型的變量
- 接口中所有的方法都沒有方法體
- 在Golang中,一個自定義類型要實作某個接口,該自定義類型需要将接口的所有方法都實作
- 一個自定義類型隻有實作了某個接口,才能将該自定義類型的執行個體(變量)賦給給接口。案例詳見1
- 隻要是自定義類型就可以實作接口,不僅僅是結構體類型
- 一個自定義類型可以實作多個接口
package main
import "fmt"
// 定義接口AInterface
type AInterface interface {
Hello()
}
// 定義解決BInterface
type BInterface interface {
World()
}
// 定義結構體類型,同時實作接口AInterface、BInterface
type AStruct struct {
}
// 實作接口AInterface
func (a AStruct) Hello() {
fmt.Println("Hello")
}
// 實作接口BInterface
func (a AStruct) World() {
fmt.Println("World")
}
func main() {
// a同時實作了接口AInterface、BInterface
a := AStruct{}
a.Hello()
a.World()
var ainterface AInterface
ainterface = a
ainterface.Hello() // AInterface隻能調用自己定義的方法
var binterface BInterface
binterface = a
binterface.World() // BInterface隻能調自己定義的方法
}
- 接口定義中不能有任何變量
- 一個接口(比如A接口)可繼承多個别的接口(比如B,C接口),這時要實作A接口,也必須将B,C接口的方法全部實作
package main
import "fmt"
type B interface {
b()
}
type C interface {
c()
}
// A接口繼承了B,C接口
type A interface {
B
C
a() // A接口自定義方法
}
type Stu struct{}
func (stu Stu) a() {
fmt.Println("a")
}
func (stu Stu) b() {
fmt.Println("b")
}
func (stu Stu) c() {
fmt.Println("c")
}
func main() {
stu := Stu{}
stu.a()
stu.b()
stu.c()
fmt.Println("-----------")
var a A
a = stu
a.a()
a.b()
a.c()
}
- interface類型預設是一個指針(引用類型),如果沒有對interface初始化就使用,會輸出nil
- 空接口interface{}沒有任何方法,是以所有類型都實作了空接口,即我們可以把任何一個變量賦給空接口
經典案例
// 接口的經典案例,使用sort.Sort對結構體切片進行排序
package main
import (
"fmt"
"math/rand"
"sort"
)
// 定義學生結構體類型
type Student struct {
Name string
Age int
}
// 定義學生切片
type StudentSlice []Student
// 實作Interface擷取長度接口
func (s StudentSlice) Len() int {
return len(s)
}
// 實作Interface接口,Less方法決定使用什麼标準排序
// Less方法報告索引i的元素是否比索引j的元素小。i小為正序,i大為降序
func (s StudentSlice) Less(i, j int) bool {
return s[i].Age < s[j].Age
}
// 實作Interface接口,Swap方法交換切換的資料
func (s StudentSlice) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func main() {
var studentSlice StudentSlice
// 循環給學生切片追加資料
for i := 0; i < 10; i++ {
student := Student{
Name: fmt.Sprintf("宋江_%d", rand.Intn(100)),
Age: rand.Intn(100),
}
studentSlice = append(studentSlice, student)
}
fmt.Println(studentSlice)
fmt.Println("-----------排序後-----------")
sort.Sort(studentSlice)
fmt.Println(studentSlice)
}