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() string
和Attack()
,在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實現。
需要注意的要點
- 學習go語言時,切忌將其他OO語言的概念強加到go語言中,要以go語言的方式去思考和編寫代碼,本文中用了很多OO的概念和詞匯旨在比較通俗的介紹go語言的基本概念,而不是要讀者站在其他語言的角度去思考go語言
- interface是go語言中非常重要的概念和經常使用的工具,為了更好的理解go語言的interface的概念,有條件的讀者可以參閱Effective Go中關於interface的描述