天天看點

golang結構體-對象和指針-函數賦予

1、定義一個結構體

2、初始化一個結構體

  有兩種情況,一是得到結構體的對象,一是得到結構的對象指針,分别有三種方式:

3、對象與對象指針的差別(更确切的說應該是值類型和指針類型)

  與C/C++類似,GO語言也存在對象與對象的指針,但不同的是,GO語言中沒有 -> 操作符來調用指針所屬的成員,而與一般對象一樣,都是使用 . 來調用。

  對于一個函數(或方法),如果函數的參數(或接收者)是對象指針時,表示此對象是可被修改的;相反的,如果是對象時,表示是不可修改的(但如果該對象本身就是引用類型,如 map\func\chan 等,則本質上是可以修改的)。是以一般的做法是,方法的接收者習慣性使用對象指針,而不是對象,一方面可以在想修改對象時進行修改,另一方面也減少參數傳遞的拷貝成本。

  另外,有一點尤為特殊,如果是作為函數的參數,則函數定義時,是使用對象還是對象指針,是有本質差別的,在使用對象作為參數的函數中,不能傳入對象指針,同樣的,在使用對象指針作為參數的函數中,也不能傳入對象,否則編譯器會報錯。但如果是方法,則接收者定義為對象還是對象指針,都可以接收對象和對象指針的調用。下面我們來定義相關的函數和方法如下:

   然後測試一下函數跟方法的調用:

   既然對于對象與對象指針的差別,方法的處理很特殊,那麼将一個對象傳入到接收者為對象指針的方法中,及将一個對象指針傳入到一個接收者為對象的方法中,能不能修改傳入對象的值呢?答案是,由方法的定義決定,而不是方法的調用者類型決定。

4、匿名字段

  結構體裡的字段可以隻有類型名,而沒有字段名,這種字段稱為匿名字段。匿名字段可以是一個結構體、切片等複合類型,也可以是 int 這樣的簡單類型。但建議不要把簡單類型作為匿名字段。

一個命名為S的結構體類型将不能再包含S類型的成員:因為一個聚合的值不能包含它自身。(該限制同樣适應于數組。)但是S類型的結構體可以包含<code>*S</code>指針類型的成員,這可以讓我們建立遞歸的資料結構,比如連結清單和樹結構等。

如果結構體沒有任何成員的話就是空結構體,寫作struct{}。它的大小為0,也不包含任何資訊,但是有時候依然是有價值的。有些Go語言程式員用map帶模拟set資料結構時,用它來代替map中布爾類型的value,隻是強調key的重要性,但是因為節約的空間有限,而且文法比較複雜,所有我們通常避免避免這樣的用法。

得意于匿名嵌入的特性,我們可以直接通路葉子屬性而不需要給出完整的路徑:

不幸的是,結構體字面值并沒有簡短表示匿名成員的文法, 是以下面的語句都不能編譯通過:

到目前為止,我們看到匿名成員特性隻是對通路嵌套成員的點運算符提供了簡短的文法糖。稍後,我們将會看到匿名成員并不要求是結構體類型;其實任何指令的類型都可以作為結構體的匿名成員。但是為什麼要嵌入一個沒有任何子成員類型的匿名成員類型呢?

答案是匿名類型的方法集。簡短的點運算符文法可以用于選擇匿名成員嵌套的成員,也可以用于通路它們的方法。實際上,外層的結構體不僅僅是獲得了匿名成員類型的所有成員,而且也獲得了該類型導出的全部的方法。這個機制可以用于将一個有簡單行為的對象組合成有複雜行為的對象。組合是Go語言中面向對象程式設計的核心

結體體定義時,可以為每一個字段添加一個 Tag,比如使用内置Json庫時,就可能用到這個Tag。具體看中繼資料和反射。