乙個典型的型別系統通常包含如下基本內容:
相比之下,go語言中的大多數型別都是值語義,並且都可以包含對應的操作方法。在需要
的時候,你可以給任何型別(包括內建型別)「增加」新方法。而在實現某個介面時,無需從
該介面繼承(事實上,go語言根本就不支援物件導向思想中的繼承語法),只需要實現該介面
要求的所有方法即可。任何型別都可以被 any 型別引用。 any型別就是空介面,即inte***ce{} 。
例如:
package main
import (
"fmt"
)//定義乙個新的型別
type integer int
func main()
}//定義方法,呼叫者為integer型別,接受integer型別,返回bool值
func (a integer) less(b integer) bool
在這個例子中,我們定義了乙個新型別 integer ,它和 int 沒有本質不同,只是它為內建的
int 型別增加了個新方法 less() 。這樣實現了integer後,就可以讓整型像乙個普通的類一樣使用了.
上面的方法的呼叫方式是 型別.方法名(引數列表),例如:
a.less(4)
這種呼叫方式就是物件導向的體現.
他和面向過程有明顯的區別,如下修改為面向過程的方法定義.
func integer_less(a,b integer)bool
呼叫方式是 方法名(引數列表),例如:
integer_less(a,2)
這有時會是個額外成本,因為物件有時很小(比如4位元組),用指標傳遞並不划算。
只有在你需要修改物件的時候,才必須用指標。它不是go語言的約束,而是一種自然約束。
舉個例子:
package main
import (
"fmt"
)//定義乙個新的型別
type integer int
func main()
//通過integer的指標呼叫
func (a *integer) add(b integer)
執行該程式,得到的結果是: a=6 。
如果你實現成員方法時的呼叫者不是a的指標而是值(即傳入integer,而非 *integer)
如下所示
func (a integer) add(b integer)
那麼執行程式得到的結果是a=3
也就是維持原來的值,這點需要特別注意.
究其原因,是因為go語言和c語言一樣,型別都是基於值傳遞的。要想修改變數的值,只能
傳遞指標。
值語義和引用語義的差別在於賦值
如果b的修改不會影響a的值,那麼此型別屬於值型別。如果會影響a的值,那麼此型別是引用型別。
go語言中的大多數型別都基於值語義,包括:
var a = [3]int
var b = a
b[1]++
fmt.println(a, b)
該程式的執行結果如下:
[1 2 3] [1 3 3]。
這表明 b=a 賦值語句是陣列內容的完整複製。要想表達引用,需要用指標:
var a = [3]int
var b = &a
b[1]++
fmt.println(a, *b)
該程式的執行結果如下:
[1 3 3] [1 3 3]
這表明 b=&a 賦值語句是陣列內容的引用。變數 b 的型別不是 [3]int ,而是 *[3]int 型別。
go語言中有4個型別比較特別,看起來像引用型別,如下所示。
1.陣列切片:指向陣列(array)的乙個區間。
2.map:極其常見的資料結構,提供鍵值查詢能力。
3.channel:執行體(goroutine)間的通訊設施。
4.介面(inte***ce):對一組滿足某個契約的型別的抽象。
但是這並不影響我們將go語言型別看做值語義。
陣列切片本質上是乙個區間,你可以大致將 t 表示為:
type slice struct
因為陣列切片內部是指向陣列的指標,所以可以改變所指向的陣列元素並不奇怪。陣列切片
型別本身的賦值仍然是值語義
go語言的結構體(struct)和其他語言的類(class)有同等的地位,但go語言放棄了包括繼
承在內的大量物件導向特性,只保留了組合(composition)這個最基礎的特性。
組合甚至不能算物件導向特性,因為在c語言這樣的過程式程式語言中,也有結構體,也有
組合。組合只是形成復合型別的基礎。
上面我們說到,所有的go語言型別(指標型別除外)都可以有自己的方法。在這個背景下,
go語言的結構體只是很普通的復合型別,平淡無奇。例如,我們要定義乙個矩形型別:
type rect struct
//然後我們定義成員方法 area() 來計算矩形的面積:
func (r *rect) area() float64
可以看出go語言中結構體的使用方式與c語言並沒有明顯不同。 Go語言學習 十三 物件導向程式設計 繼承
go語言也提供了繼承,但是採用了組合的方式,所以我們將其稱為匿名組合 package main import fmt 定義基類 type base struct 基類相關的2個成員方法 func base base a func base base b 定義子類 type son struct 重寫...
Go語言學習 十三 物件導向程式設計 繼承
package main import fmt 定義基類 type base struct 基類相關的2個成員方法 func base base a func base base b 定義子類 type son struct 重寫基類的b方法 func son son b func main son...
Go語言學習十一 go語言切片
go 語言切片是對陣列的抽象。go 陣列的長度不可改變,在特定場景中這樣的集合就不太適用,go中提供了一種靈活,功能強悍的內建型別切片 動態陣列 與陣列相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。你可以宣告乙個未指定大小的陣列來定義切片 var identifier typ...