結構體是一種聚合的數據類型,是由零個或多個任意類型的值聚合成的實體,每一個值稱爲結構體的成員。下面分兩方面介紹:一個是基礎部分,一個是看一下結構體在實際內存中的內存模型。golang
1 基礎
1.1 定義
- type structName typeName {} ###1.2 聲明
- var varName structName ###1.3 初始化
- type Point struct{ X, Y int } p := Point{1, 2}
- anim := gif.GIF{LoopCount: nframes} 此建立方式結構體成員順序不重要。 ###1.4 new
- new(structType)
- new出來的是結構體指針。
1.5 特性
- 結構體成員相同,順序不一樣不是相同結構體類型。
- 結構體成員以大寫字母能夠導出,小寫的不能夠導出。
- 結構體類型不能再包含形同類型的成員:由於一個聚合的值不能包含它自身。但結構體能夠包含相同類型的指針類型的成員,這可讓咱們建立遞歸的數據結構,好比鏈表和樹結構等。
- 結構體類型的零值對應的是每一個成員相應類型的零值。
- 若是結構體沒有任何成員的話就是空結構體,寫做struct{}。它的大小爲0,也不包含任何信息,可是有時候依然是有價值的。好比在管道中傳遞的數據若是隻緊起到信號做用那徹底能夠用struct{}以便節省空間。
1.6 函數傳參
- 值傳遞,若是結構體比較大的話最好指針傳遞。
1.7 結構體比較
- 若是結構體的所有成員都是能夠比較的,那麼結構體也是能夠比較的,那樣的話兩個結構體 將可使用==或!=運算符進行比較。
1.8 匿名成員
- 只聲明一個成員對應的數據類型而不指名成員的名字,這類成員就叫匿名成員。
- 由於匿名成員也有一個隱式的名字,所以不能同時包含兩個類型相同的匿名成員,這會致使 名字衝突。
1.9 嵌套
結構體能夠嵌套另外一個結構體。 結構體能夠包含結構體類型的匿名成員,這樣能夠經過p.b就能夠訪問匿名成員結構體中的b。json
1.10 標籤
1.10.1 標籤主要應用於json字符串與結構體成員的相互轉換的映射關係,見下方代碼實例:
type User struct { UserId int `json:"user_id"` UserName string `json:"user_name"` } u := &User{UserId: 1, UserName: "xitehip"} j, _ := json.Marshal(u) fmt.Println(string(j)) // 輸出內容:{"user_id":1,"user_name":"tony"} 複製代碼
1.10.2 struct成員變量標籤獲取
t := reflect.TypeOf(u) field := t.Elem().Field(0) fmt.Println(field.Tag.Get("json")) 複製代碼
關於映射後續會有專門章節講解。bash
2 內存佈局
代碼實例:數據結構
type Person struct { age int class int name string } var pp *Person func main() { p := Person{age:18, class:8, name:"xitehip"} pp = &p fmt.Println(*pp) } 複製代碼
編譯生成的可執行文件,而後用gdb去分析內存佈局見下圖1 函數
由圖1能夠發現,結構體中的元素確實是連續排布的,只不過成員name存儲的是指針。打印name指針的值發現確實是xitehip(可查看ascii表)這個字符串。oop
3 總結結構體是一種存儲複合數據,主要應用於一個實體有多個數據類型的場景。在golang面向對象思想中,結構體也應用很是普遍,在後續的文章會詳細講解golang中的面向對象。佈局
參考go語言聖經ui