go語言,struct and interface(golang)(二)


go語言包含但不限於int32,float32,chan,map,slice等內建類型,同時為了能讓用戶定義自己的類型,go語言為我們提供了struct和interface這兩種好用的工具

結構體(Struct)

和C語言的struct相似,在go語言中,我們依然用struct來聲明一個結構體比如:

type gameObject struct{
    name string
}

以上代碼聲明了一個名為gameObject的結構體,該結構體包含類型為string的字段name。
在go語言中,所有的類型名都是放在變量后面的,這也是go語言跟C/C++,JAVA,C#等語言區別比較大的地方。
既然有了struct,那有沒有class呢?
沒有class,go語言中的“面向對象”概念和上面提到的幾種語言是有很大區別的,后面會講到

嵌入(Embedding)

go語言中的“繼承”和其他語言中的繼承有很大區別,比如:

type player struct{
    gameObject
}

這是一種“繼承”的寫法,在go語言中這種方式叫做“嵌入”(embed),此時player類型就擁有了gameObject類型的name變量

方法(Method)

在go語言中,我們可以為自定義類型定義類型相關的方法,比如:

func (p *player) Name() string{
    return p.name
}

上面的代碼為player這個自定義類型聲明了一個名為Name的方法,該方法返回一個string。值得注意的是(p *player)這段代碼指定了我們是為player創建方法,並將調用該方法的實例指針當作變量p傳入該函數,如果沒有(p *player)這段代碼,這個方法就變成了一個普通的全局函數。

接口(interface)

go語言中接口的概念和其他語言中的接口概念非常相似,比如:

type challenger interface {
    Name() string
    Attack()
}

上面的代碼聲明了一個名為challenger的接口,這個接口包含2個函數(行為)Name() stringAttack(),在go語言中,只要實現了接口中定義的全部函數,就認為實現了該接口,所以所有的類型都實現了interface{}接口,interface{}類型的變量也被當作go語言中的void*指針來使用。

接口的運用

參考以下代碼:

package main 
import "fmt"

type gameObject struct {
    name string
}
func (o *gameObject) Name() string{
    return o.name
}
func (o *gameObject) Attack() {
    fmt.Printf("GameObject %s do not know how to attack\n", o.name)
}

type player struct {
    gameObject
}
func (p *player) Attack(){
    fmt.Printf("player %s attacks\n", p.name)
}

type monster struct {
    gameObject
}

type challenger interface {
    Name() string
    Attack()
}

func main(){
    p := &player{gameObject : gameObject{name:"devgl"}}
    m := &monster{gameObject : gameObject{name:"slime"}}
    Attack(p)
    Attack(m)
}

func Attack(c challenger) {
	c.Attack()
}

上面這段代碼聲明了兩個內嵌gameObject自定義類型player和monster,其中,gameObject實現了challenger接口的所有函數,因此gameObject實現了challenger接口,那么,我們可以說player和monster這兩個自定義類型也實現了該接口。除此之外,player類型定義了自己的Attack函數實現,在main函數中,我們創建了p,m兩個對象分別對應player和monster,並將對象的指針傳入Attack全局函數。這里可以注意到Attack全局函數的參數是一個challenger接口,而player,monster都實現了這個接口,所以這樣傳值沒有問題,程序輸出:

player devgl attacks
GameObject slime do not know how to attack

注意第二行是m.Attack()的輸出,因為monster沒有定義自己的Attack函數,所以go語言幫我們找到了gameObject的Attack實現。

需要注意的要點

  1. 學習go語言時,切忌將其他OO語言的概念強加到go語言中,要以go語言的方式去思考和編寫代碼,本文中用了很多OO的概念和詞匯旨在比較通俗的介紹go語言的基本概念,而不是要讀者站在其他語言的角度去思考go語言
  2. interface是go語言中非常重要的概念和經常使用的工具,為了更好的理解go語言的interface的概念,有條件的讀者可以參閱Effective Go中關於interface的描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM