go 通過型別別名(alias types)和結構體的形式支援使用者自定義型別,或者叫定製型別。試圖表示乙個現實世界中的實體。
結構體由一系列命名的元素組成,這些元素又被稱為字段,每個欄位都有乙個名稱和乙個型別。
結構體的目的就是把資料聚集在一起,以便能夠更加便捷地操作這些資料。結構體的概念在 c 語言裡很常見,被稱為 struct。golang 中的結構體也是 struct。go 語言中沒有類的概念,因此在 go 中結構體有著更為重要的地位。結構體是復合型別(composite types),當需要定義乙個型別,它由一系列屬性組成,每個屬性都有自己的型別和值的時候,就應該使用結構體,它把資料聚集在一起。然後可以訪問這些資料,就好像它是乙個獨立實體的一部分。結構體也是值型別,因此可以通過 new 函式來建立。
在 golang 中最常用的方法是使用關鍵字 type 和 struct 來定義乙個結構體,以關鍵字 type 開始,之後是新型別的名字,最後是關鍵字 struct:
//person 為使用者定義的乙個型別
type person struct
還有一些簡單的寫法,比如:
type t struct
也是合法的,它更適用於簡單的結構體。
結構體裡的字段都有名字,比如上面例子中的 name、age 和 email 等等。如果乙個欄位在**中從來不會被用到,那可以把它命名為 _,即空識別符號。
結構體中的字段可以是任何型別,甚至是結構體本身,也可以是函式或者介面。可以宣告結構體型別的乙個變數,然後像下面這樣給它的字段賦值:
var p personp.name = "
nick
"p.age = 28
另外,陣列可以看作是一種結構體型別,不過它使用下標而不是具名的字段。
字段標記
在定義結構體時還可以為字段指定乙個標記資訊:
type person struct
這些標記資訊通過反射介面可見,並參與結構體的型別標識,但在其他情況下被忽略。
一旦定義了結構體型別就可以使用這個型別建立值。
使用結構型別宣告變數,並初始化為零值
var nick person
關鍵字 var 建立了型別為 person 且名為 nick 的變數。nick 被稱作型別 person 的乙個例項(instance)或物件(object)。注意:當宣告變數時,這個變數對應的值總是會被初始化。這個值要麼用指定的值初始化,要麼用零值(即變數型別的預設值)做初始化。對數值型別來說,零值是 0;對字串來說,零值是空字串;對布林型別,零值是 false。
通過上面的方式宣告結構體型別的變數,結構體裡的每個欄位都會用零值初始化。任何時候,建立乙個變數並初始化為零值,習慣上會使用關鍵字 var。這種用法是為了更明確地表示乙個變數被設定為零值。
使用結構體字面量宣告變數,並初始化為非零值
如果希望變數被初始化為某個非零值,可以通過結構體字面量和短變數宣告操作符(:=)來建立變數。下面的**展示了如何宣告乙個 persion 型別的變數,並使用某個非零值作為初始值。
//宣告 person 型別的變數,並初始化所有字段
nick :=person
在第一行中我們給出了乙個變數名 nick,之後是短變數宣告操作符。這個操作符是冒號加乙個等號 (:=)。乙個短變數宣告操作符在一次操作中完成兩件事情:宣告乙個變數,並初始化。短變數宣告操作符會使用右側給出的型別資訊作為宣告變數的型別。
短變數宣告操作符(:=)
它的作用是宣告並且賦值乙個變數,其好處是不需要寫 var 三個字母,另外不需要寫型別,golang 語言會自動根據賦值的內容確定型別。
使用短變數宣告操作符也有一些限制,比如不能在函式外面使用,即不能用來宣告全域性變數。另外短變數宣告操作符左邊至少得有乙個變數是沒有定義過的。
字面量的兩種寫法
結構體字面量可以對結構體型別進行初始化,比如前面介紹過的示例:
nick :=person
這種形式在不同行宣告每個欄位的名字以及對應的值。欄位名與值用冒號分隔,每一行以逗號結尾。這種形式對字段的宣告順序沒有要求。
第二種形式沒有欄位名,只宣告對應的值,如下面的**:
nick := person
每個值也可以分別佔一行,不過習慣上這種形式會寫在一行裡,結尾不需要逗號。這種形式
下,值的順序很重要,必須要和結構宣告中字段的順序一致。
new 是乙個用來分配記憶體的內建函式,但是與 c++ 不一樣的是,它並不初始化記憶體,只是將其置零。也就是說,new(t) 會為型別 t 分配被置零的記憶體,並且返回它的位址,乙個型別為 *t 的值。在 golang 的術語中,其返回乙個指向新分配的型別為 t 的指標,這個指標指向的內容的值為零(zero value)。比如下面的**:
nick := new(person)
這裡的變數 nick 是乙個指標:
fmt.printf("%t", nick)
輸出的結果為:*main.student
而通過下面方式宣告的變數:
var nick person
型別則是:main.student
使用 new 函式時,宣告變數和分配記憶體並不需要放在一起,可以先宣告乙個變數,然後再通過 new 函式為之分配記憶體,比如下面的寫法:
var nick *person
nick = new (person)
new 函式的特點是只能把記憶體初始化為零值並返回其指標,如果要通過字面量初始化該記憶體就需要使用混合字面量語法(composite literal syntax):
&t
比如下面的寫法:
nick := &person
此時 nick 的型別也是 *person。因此我們可以得出下面的結論:
表示式 new(type) 和 &type{} 是等價的。
在 golang 中,訪問結構體成員需要使用點號操作符,點號操作符也被稱為選擇器(selector),使用時的格式為:
結構體.成員名
注意:這裡的 "結構體" 是指結構體型別的變數或結構體指標型別的變數。無論變數是乙個結構體型別還是乙個結構體型別指標,都可以使用相同的選擇器服務來引用結構體的字段。
結構體可以包含乙個或多個匿名(或者稱為內嵌)字段,即這些字段沒有顯式的名字。僅指明欄位的型別,此時該型別就是欄位的名字。匿名字段本身可以是乙個結構體型別,即結構體可以包含內嵌的結構體。
匿名字段
匿名欄位和物件導向程式設計中的繼承概念相似,可以被用來模擬類似繼承的行為。golang 中的基礎就是通過內嵌或組合來實現的,所以說在 golang 中組合比繼承更受歡迎。比如下面的例子:
type test struct
內嵌結構體
結構體也是一種資料型別,所以它同樣可以作為匿名字段使用:
type person structtype student struct
下面的**可以宣告並初始化 student 型別的變數:
st :=student ,studentid:
1000
,}
從這個示例可以看出,內層結構體被簡單地插入或者內嵌進外層結構體。這種簡單的 "繼承" 機制使得 golang 很輕鬆就能實現從乙個或一些型別中繼承部分或全部的實現。
golang 中沒有類的概念,因此在 golang 中結構體有著更為重要的地位。所以學習並掌握結構體是入門 golang 的關鍵步驟。希望本文能夠幫助大家理解 golang 結構體的基本概念和用法。
參考:
golang struct types
《go語言程式設計入門與實戰技巧》
結構體定義
go 語言的變數宣告並賦值運算子(:=)
Golang結構體知識
在看docker原始碼時,碰到了這個語句 container.lock 看到上面直接對struct container進行上鎖時,我翻了一下這個結構體,發現沒有定義任何鎖啊,怎麼上鎖的咧。於是我就翻了一下這個結構 體的一些子屬性,發現了state的定義 container container.go ...
Golang 學習 結構體
結構體定義 結構體是一種資料型別。定義型別 地位等價於 int byte bool string.通常放在全域性位置 type person struct 注意 結構體內不能賦初值,不能用 var 修飾。普通變數定義和初始化 普通變數的賦值和使用 使用 索引成員變數。var man person m...
Golang結構體初探
go語言中的基礎資料型別可以表示一些事物的基本屬性,但是當我們想表達乙個事物的全部或部分屬性時,這時候再用單一的基本資料型別明顯就無法滿足需求了,go語言提供了一種自定義資料型別,可以封裝多個基本資料型別,這種資料型別叫結構體,英文名稱struct。也就是我們可以通過struct來定義自己的型別了。...