關於go介面的一些說明

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

什麼是介面

介面是golang最重要的特性之一,在Go中,介面interface其實和其他語言的介面意思沒什麼區別。interface理解其為一種類型的規範或者約定。一種類型是不是“實現”了一個介面呢?就看這種類型是不是實現了介面中定義的所有方法。接⼝是一個或多個方法簽名的集合,任何非介面類型只要擁有與之對應的全部方法實現 (包括相同的名稱、參數列表以及傳回值。),就表示它"實現" 了該介面,無需顯式在該類型上添加介面聲明。此種方式又被稱作Duck Type。

介面的執行個體化

介面是可被執行個體化的類型,而不僅僅是語言上的約束規範。當我們建立介面變數時,將會為其分配記憶體,並將賦值給它的對象拷貝儲存。將對象賦值給介面變數時,會發生值拷貝行為。沒錯,介面內部儲存的是指向這個複製品的指標。而且我們無法修改這個複製品的狀態,也無法擷取其指標。

package mainimport ("fmt")type Painter interface {Draw()}type Xiaowang struct {}func (Xiaowang) Draw() {fmt.Println("i am drawing a paper.") //畫畫}func main() {var xw Xiaowangvar painter Painter = xwpainter.Draw()var painter2 Painter = &xwpainter2.Draw()painter3 := Painter(xw)painter3.Draw()painter4 := Painter(&xw)painter4.Draw()}

此程式中,以上的執行個體化方法都正確,因為runtime會幫我們調整*和非*。

但如果將Draw前面的接收者改為*Xiaowang,即:

func (*Xiaowang) Draw() {fmt.Println("i am drawing a paper.") //畫畫}

那麼非指標的執行個體化就會出錯,提示如下:

.\main.go:25: cannot use xw (type Xiaowang) as type Painter in assignment:Xiaowang does not implement Painter (Draw method requires pointer receiver).\main.go:29: cannot convert xw (type Xiaowang) to type Painter:Xiaowang does not implement Painter (Draw method requires pointer receiver)

介面的面向類型

在golang中,type很好地實現了一對多,也就是利用這個type關鍵字可以定義出多種多樣的不同類型。而interface很好地支援了多對一,即任何類型都可以被interface類型接收。

Go語言裡可以使用type關鍵字來把一個類型來轉換成另外一個類型而保持資料的本質不變,例如:

type Age inttype Height inttype Grade int
type絕不只是對應於C/C++中的typedef, 它不是用於定義一系列的 別名它的作用是定義 一系列互不相干的行為特徵:通過這些互不相干的行為特徵, 本質上同一的事物表現出不同事物的特徵。以上面的代碼為例:int還是那個int,Age、Height、Grade都是int,但通過type以int為基礎類型定義出的不同類型,就完全不相干了;Age、Height、Grade是完全不同的類型(也就是面向不同的對象)。我們可以分別為Age、Height、Grade定義出下列不同的行為(表示為方法或者函數):
func (a Age) Old() bool {    return a > 50}func (l Length) NeedTicket() bool {    return l > 120}func (g Grade) Pass() bool {    return g >= 60}
這樣就區分開了以int為基礎類型的各種衍生類型。再看一個複雜一些的例子:
type Painter interface {    Draw()}type Cowboy interface {    Draw()}type Xiaoming struct {}type XiaomingAsPainter Xiaomingfunc (p *XiaomingAsPainter) Draw() {    fmt.Println("I'm painting.")}func main() {    var xm Xiaoming    var painter Painter = (*XiaomingAsPainter)(&xm)    painter.Draw()}
上面的兩個介面都包括了Draw()方法,如果類型小明只是一個畫家,那麼怎麼實現畫家介面呢?這裡就需要理解一個概念: interface並不是孤立存在的,它是type的抽象。而同一個事物/資料可以有多個type。小明是個人(這裡實現為一個struct),畫家只是他的一種身份,因此把畫家的行為特性獨立出來作為一個type,同時也是Painter介面的實現。如果想讓他以畫家的身份示人,只要把小明轉換到畫家的身份就可以(通過語句"var painter Painter = (*XiaomingAsPainter)(&xm)")。這樣,小明還會被誤認為是牛仔嗎?顯然沒有這個可能性。

那麼如果小王既是畫家又是牛仔,只要讓小王同時具有牛仔和畫家的身份(類型)就可以:

type Painter interface {    Draw()}type Cowboy interface {    Draw()}type Xiaowang struct {}type XiaowangAsPainter Xiaowangfunc (p *XiaowangAsPainter) Draw() {    fmt.Println("I'm painting.")}type XiaowangAsCowboy Xiaowangfunc (p *XiaowangAsCowboy) Draw() {    fmt.Println("I'm drawing.")}func main() {    var xw Xiaowang    var painter Painter = (*XiaowangAsPainter)(&xw)    painter.Draw()    var cowboy Cowboy = (*XiaowangAsCowboy)(&xw)    cowboy.Draw()}

go的實現把不同類型的行為特性區分開來,又從資料本質的層面把它們聯絡在一起(都是一個人的不同身份),這充分體現了go語言對對象和資料的理解。

通俗一點說就是定義出不同的類型,再根據這些類型分別定義相應的方法。這樣不同的類型就分別實現了不同的介面,雖然這些類型的未經處理資料可能是一樣的。這也體現了物件導向編程的思想。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.