Go語言學習筆記(七)介面

2021-09-10 01:32:32 字數 4557 閱讀 8649

go語言中的介面作用類似於c++中的虛函式機制,可以提供乙個統一呼叫的方式。

介面是雙方約定的一種合作協議。介面實現者不需要關心介面會被怎樣使用,呼叫者也不需要關心介面的實現細節。介面是一種型別,也是一種抽象結構,不會暴露所包含資料的格式、型別及結構。

每個介面型別由多個方法組成。

type 介面型別名 inte***ce 

一般地:

介面型別名:go語言介面在命名時,一般會在單詞後面新增er,如有字串功能的介面叫stringer

方法名:當方法名首字母大寫時,且這個介面型別名首字母也是大寫時,這個方法可以被介面所在的包之外的**訪問

引數列表、返回值列表:引數列表和返回值列表中的引數變數名可以被忽略

在型別中新增與介面簽名一致的方法就可以實現該方法。簽名包括該方法中方法名、引數列表和返回引數列表。也就是說,只要實現介面型別中的方法名稱、引數列表、返回引數列表中的任意一項與介面要實現的方法不一致,那麼介面的這個方法就不會被實現。

package main

import (

"fmt"

)// 定義乙個資料寫入器

type datawriter inte***ce ) error

}// 定義檔案結構,用於實現datawriter

type file struct

// 實現datawriter介面的writedata方法

func (d *file) writedata(data inte***ce{}) error

func main()

當乙個介面中有多個方法時,只有這些方法都被實現了,介面才能被正確編譯並使用。

package main

import (

"fmt"

)type datawriter inte***ce ) error

foo() //新增介面函式,但是沒有實現

}type file struct

func (d *file) writedata(data inte***ce{}) error

func main()

上面**執行時,會提示如下錯誤:

: cannot use f (type *file) as type datawriter in assignment:

*file does not implement datawriter (missing foo method)

在go語言中,不僅結構體與結構體之間可以巢狀,介面與介面間也可以通過巢狀創造出新的介面。

介面與介面巢狀組合而成了新介面,只要介面的所有方法被實現,則這個介面中的所有巢狀介面的方法可以被呼叫。

package main

import (

"io"

)// 宣告乙個裝置結構

type device struct

// 實現io.writer的write()方法

func (d *device) write(p byte) (n int, err error)

// 實現io.closer的close()方法

func (d *device) close() error

func main()

go語言中使用介面斷言將介面轉換成另外乙個介面,也可以將介面轉換為另外的型別。介面的型別在開發中非常常見,使用也非常頻繁。

t := i.(t)

i為介面變數,t為轉換的目標型別,t代表轉換後的變數

如果i沒有完全實現t介面的方法這個語句將會觸發宕機。觸發宕機不是很友好,所以有另一種寫法:

t, ok := i.(t)

可以通過判斷ok的值檢視介面是否實現。

package main

import "fmt"

// 定義飛行動物介面

type flyer inte***ce

// 定義行走動物介面

type walker inte***ce

// 定義鳥類

type bird struct

// 實現飛行動物介面

func (b *bird) fly()

// 為鳥新增walk()方法, 實現行走動物介面

func (b *bird) walk()

// 定義豬

type pig struct

// 為豬新增walk()方法, 實現行走動物介面

func (p *pig) walk()

func main()

// 遍歷對映

for name, obj := range animals

// 如果是行走動物則呼叫行走動物介面

if iswalker

}}

介面在轉換在轉換為其他型別時,介面內儲存的例項對應的型別指標,必須是要準換的對應的型別指標。

p1 := new(pig)

var a walker = p1

p2 := a.(*pig) //正確

p2 := a.(*bird) //錯誤

空介面是介面型別的特殊形式,空介面沒有任何方法,因此任何型別都無需實現空介面。從實現的角度看,任何值都滿足這個介面的需求。因此空介面型別可以儲存任何值,也可以從空介面中取出原值。

空介面的內部實現儲存了物件的型別和指標。使用空介面儲存以資料的過程會比直接用資料對應型別的變數儲存稍慢。因此在開發中,應在需要的地方使用空介面,而不是在所有地方使用空介面。

空介面型別類似於c語言中的void*。

var any inte***ce{}

any = 1 //將整型儲存到空介面

fmt.println(any)

any = "hello" //將字串儲存到空介面

fmt.println(any)

any = false //將bool型儲存到空介面

fmt.println(any)

儲存到空介面的值,如果直接取出指定型別的值時,會發生編譯錯誤:

var a int = 1

var i inte***ce{} = a

//錯誤

var b int = i

//正確

b, ok := i.(int)

if ok

var a inte***ce{} = 12

var b inte***ce{} = "hello,hust"

fmt.println(a == b) //false

當介面中儲存有動態型別的值時,執行時將觸發錯誤。

型別的可比較性如下:

型別說明

map宕機錯誤,不可比較

切片(t)

宕機錯誤,不可比較

通道可比較,必須由同乙個make生成,也就是同乙個通道才會為true,否則為false

陣列可比較,編譯器知道兩個陣列是否一致

結構體可比較,可以逐個比較結構體的值

函式可比較

var a inte***ce{} = int

var b inte***ce{} = int

fmt.println(a == b)

panic: runtime error: comparing uncomparable type int

go語言的switch不僅可以像其他語言一樣實現數值、字串的判斷,還有一種特殊的用途----判斷乙個介面內儲存或實現的型別。

switch 介面變數.(type)
package main

import (

"fmt"

)func printtype(v inte***ce{})

}func main() )

}//執行結果:

1 is int

hello is string

false is bool

[1 2] is int slice

多個介面進行型別斷言時,可以使用型別分支簡化判斷過程。

package main

import "fmt"

type cantaincanusefaceid inte***ce

type cantainstolen inte***ce

type alipay struct

func (a *alipay) canusefaceid()

type cash struct

func (c *cash) stolen()

func print(paymethod inte***ce{})

}func main()

//執行結果:

*main.alipay can use faceid

*main.cash may be stolen

7 1 介面摘自《go語言學習筆記》

1,介面實現機制 只要目標方法集內包含介面宣告的全部方法,就被視為實現了該介面,無需做顯示宣告。目標型別可以實現多個介面。2,內部實現,介面自身也是一種結構型別 type iface struct不能有欄位 不能定義自己的方法。只能宣告方法,不能實現。可嵌入其它介面型別。3,介面通常以er作為介面字...

Go語言學習筆記 PART9 介面

go語言不是傳統的物件導向程式設計語言,沒有類和繼承的概念,但是有非常靈活的介面,可以實現物件導向的特徵,介面提供一種方式來說明物件的行為 type namer inte ce 複製 1.定義乙個介面 type shaper inte ce type square struct 2.square型別...

go語言學習筆記九 介面基本使用和最佳實踐

1.基本使用 介面是引用型別package main import fmt 定義介面 type usb inte ce 定義 3個結構體 type phone struct type camera struct type computer struct 實現方法 func p phone start...