天天看點

Golang 接口筆記

基本介紹

接口是一個資料類型,可以定義一組方法,但都不需要實作。并且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 接口筆記

接口細節

  • 接口本身不能建立執行個體,但是可以指向一個實作了該接口的自定義類型的變量
Golang 接口筆記
Golang 接口筆記
  • 接口中所有的方法都沒有方法體
  • 在Golang中,一個自定義類型要實作某個接口,該自定義類型需要将接口的所有方法都實作
  • 一個自定義類型隻有實作了某個接口,才能将該自定義類型的執行個體(變量)賦給給接口。案例詳見1
  • 隻要是自定義類型就可以實作接口,不僅僅是結構體類型
Golang 接口筆記
  • 一個自定義類型可以實作多個接口
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隻能調自己定義的方法
}
           
Golang 接口筆記
  • 接口定義中不能有任何變量
Golang 接口筆記
  • 一個接口(比如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()
}
           
Golang 接口筆記
  • interface類型預設是一個指針(引用類型),如果沒有對interface初始化就使用,會輸出nil
Golang 接口筆記
  • 空接口interface{}沒有任何方法,是以所有類型都實作了空接口,即我們可以把任何一個變量賦給空接口
Golang 接口筆記

經典案例

// 接口的經典案例,使用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)
}
           
Golang 接口筆記

繼續閱讀