Golang 結(jié)構(gòu)體

Go 通過類型別名(alias types)和結(jié)構(gòu)體的形式支持用戶自定義類型蝶俱,或者叫定制類型瘦馍。試圖表示一個(gè)現(xiàn)實(shí)世界中的實(shí)體碳褒。

結(jié)構(gòu)體由一系列命名的元素組成,這些元素又被稱為字段莲组,每個(gè)字段都有一個(gè)名稱和一個(gè)類型诊胞。
結(jié)構(gòu)體的目的就是把數(shù)據(jù)聚集在一起,以便能夠更加便捷地操作這些數(shù)據(jù)锹杈。結(jié)構(gòu)體的概念在 C 語言里很常見撵孤,被稱為 struct。Golang 中的結(jié)構(gòu)體也是 struct竭望。Go 語言中沒有類的概念邪码,因此在 Go 中結(jié)構(gòu)體有著更為重要的地位。結(jié)構(gòu)體是復(fù)合類型(composite types)咬清,當(dāng)需要定義一個(gè)類型闭专,它由一系列屬性組成,每個(gè)屬性都有自己的類型和值的時(shí)候旧烧,就應(yīng)該使用結(jié)構(gòu)體影钉,它把數(shù)據(jù)聚集在一起。然后可以訪問這些數(shù)據(jù)掘剪,就好像它是一個(gè)獨(dú)立實(shí)體的一部分平委。結(jié)構(gòu)體也是值類型,因此可以通過 new 函數(shù)來創(chuàng)建夺谁。

定義結(jié)構(gòu)體
在 Golang 中最常用的方法是使用關(guān)鍵字 type 和 struct 來定義一個(gè)結(jié)構(gòu)體廉赔,以關(guān)鍵字 type 開始肉微,之后是新類型的名字,最后是關(guān)鍵字 struct:

// Person 為用戶定義的一個(gè)類型
type Person struct {
Name string
Age int
Email string
}
還有一些簡(jiǎn)單的寫法蜡塌,比如:

type T struct { a, b int }
也是合法的碉纳,它更適用于簡(jiǎn)單的結(jié)構(gòu)體。

結(jié)構(gòu)體里的字段都有名字岗照,比如上面例子中的 Name村象、Age 和 Email 等等。如果一個(gè)字段在代碼中從來不會(huì)被用到攒至,那可以把它命名為 _,即空標(biāo)識(shí)符躁劣。

結(jié)構(gòu)體中的字段可以是任何類型迫吐,甚至是結(jié)構(gòu)體本身,也可以是函數(shù)或者接口账忘≈景颍可以聲明結(jié)構(gòu)體類型的一個(gè)變量,然后像下面這樣給它的字段賦值:

var p Person
p.Name = "nick"
p.Age = 28
另外鳖擒,數(shù)組可以看作是一種結(jié)構(gòu)體類型溉浙,不過它使用下標(biāo)而不是具名的字段。

字段標(biāo)記
在定義結(jié)構(gòu)體時(shí)還可以為字段指定一個(gè)標(biāo)記信息:

type Person struct {
Name string json:"name"
Age int json:"age"
Email string json:"email"
}
這些標(biāo)記信息通過反射接口可見蒋荚,并參與結(jié)構(gòu)體的類型標(biāo)識(shí)戳稽,但在其他情況下被忽略。

聲明結(jié)構(gòu)體類型的變量
一旦定義了結(jié)構(gòu)體類型就可以使用這個(gè)類型創(chuàng)建值期升。

使用結(jié)構(gòu)類型聲明變量惊奇,并初始化為零值

var nick Person
關(guān)鍵字 var 創(chuàng)建了類型為 Person 且名為 nick 的變量。nick 被稱作類型 Person 的一個(gè)實(shí)例(instance)或?qū)ο?object)播赁。注意:當(dāng)聲明變量時(shí)颂郎,這個(gè)變量對(duì)應(yīng)的值總是會(huì)被初始化。這個(gè)值要么用指定的值初始化容为,要么用零值(即變量類型的默認(rèn)值)做初始化乓序。對(duì)數(shù)值類型來說,零值是 0坎背;對(duì)字符串來說替劈,零值是空字符串;對(duì)布爾類型沼瘫,零值是 false抬纸。

通過上面的方式聲明結(jié)構(gòu)體類型的變量,結(jié)構(gòu)體里的每個(gè)字段都會(huì)用零值初始化耿戚。任何時(shí)候湿故,創(chuàng)建一個(gè)變量并初始化為零值阿趁,習(xí)慣上會(huì)使用關(guān)鍵字 var。這種用法是為了更明確地表示一個(gè)變量被設(shè)置為零值坛猪。

使用結(jié)構(gòu)體字面量聲明變量脖阵,并初始化為非零值
如果希望變量被初始化為某個(gè)非零值,可以通過結(jié)構(gòu)體字面量和短變量聲明操作符(:=)來創(chuàng)建變量墅茉。下面的代碼展示了如何聲明一個(gè) Persion 類型的變量命黔,并使用某個(gè)非零值作為初始值。

// 聲明 Person 類型的變量就斤,并初始化所有字段
nick := Person{
Name: "nick",
Age: 28,
Email: "nickli@xxx.com",
}
在第一行中我們給出了一個(gè)變量名 nick悍募,之后是短變量聲明操作符。這個(gè)操作符是冒號(hào)加一個(gè)等號(hào) (:=)洋机。一個(gè)短變量聲明操作符在一次操作中完成兩件事情:聲明一個(gè)變量坠宴,并初始化。短變量聲明操作符會(huì)使用右側(cè)給出的類型信息作為聲明變量的類型绷旗。

短變量聲明操作符(:=)
它的作用是聲明并且賦值一個(gè)變量喜鼓,其好處是不需要寫 var 三個(gè)字母,另外不需要寫類型衔肢,Golang 語言會(huì)自動(dòng)根據(jù)賦值的內(nèi)容確定類型庄岖。

使用短變量聲明操作符也有一些限制,比如不能在函數(shù)外面使用角骤,即不能用來聲明全局變量隅忿。另外短變量聲明操作符左邊至少得有一個(gè)變量是沒有定義過的。

字面量的兩種寫法
結(jié)構(gòu)體字面量可以對(duì)結(jié)構(gòu)體類型進(jìn)行初始化启搂,比如前面介紹過的示例:

nick := Person{
Name: "nick",
Age: 28,
Email: "nickli@xxx.com",
}
這種形式在不同行聲明每個(gè)字段的名字以及對(duì)應(yīng)的值硼控。字段名與值用冒號(hào)分隔,每一行以逗號(hào)結(jié)尾胳赌。這種形式對(duì)字段的聲明順序沒有要求牢撼。
第二種形式?jīng)]有字段名,只聲明對(duì)應(yīng)的值疑苫,如下面的代碼:

nick := Person{"nick", 28, "nickli@xxx.com"}
每個(gè)值也可以分別占一行熏版,不過習(xí)慣上這種形式會(huì)寫在一行里,結(jié)尾不需要逗號(hào)捍掺。這種形式下撼短,值的順序很重要,必須要和結(jié)構(gòu)聲明中字段的順序一致挺勿。

new 函數(shù)
new 是一個(gè)用來分配內(nèi)存的內(nèi)置函數(shù)曲横,但是與 C++ 不一樣的是,它并不初始化內(nèi)存,只是將其置零禾嫉。也就是說灾杰,new(T) 會(huì)為類型 T 分配被置零的內(nèi)存,并且返回它的地址熙参,一個(gè)類型為 *T 的值艳吠。在 Golang 的術(shù)語中,其返回一個(gè)指向新分配的類型為 T 的指針孽椰,這個(gè)指針指向的內(nèi)容的值為零(zero value)昭娩。比如下面的代碼:

nick := new(Person)
這里的變量 nick 是一個(gè)指針:

fmt.Printf("%T", nick)
輸出的結(jié)果為:*main.Student
而通過下面方式聲明的變量:

var nick Person
類型則是:main.Student

使用 new 函數(shù)時(shí),聲明變量和分配內(nèi)存并不需要放在一起黍匾,可以先聲明一個(gè)變量栏渺,然后再通過 new 函數(shù)為之分配內(nèi)存,比如下面的寫法:
var nick *Person
nick = new (Person)

new 函數(shù)的特點(diǎn)是只能把內(nèi)存初始化為零值并返回其指針膀捷,如果要通過字面量初始化該內(nèi)存就需要使用混合字面量語法(composite literal syntax):
&T{...}
比如下面的寫法:

nick := &Person{
Name: "nick",
Age: 28,
Email: "nickli@xxx.com",
}
此時(shí) nick 的類型也是 *Person迈嘹。因此我們可以得出下面的結(jié)論:
表達(dá)式 new(Type) 和 &Type{} 是等價(jià)的。

選擇器(selector)
在 Golang 中全庸,訪問結(jié)構(gòu)體成員需要使用點(diǎn)號(hào)操作符,點(diǎn)號(hào)操作符也被稱為選擇器(selector)融痛,使用時(shí)的格式為:

結(jié)構(gòu)體.成員名
注意:這里的 "結(jié)構(gòu)體" 是指結(jié)構(gòu)體類型的變量或結(jié)構(gòu)體指針類型的變量壶笼。無論變量是一個(gè)結(jié)構(gòu)體類型還是一個(gè)結(jié)構(gòu)體類型指針,都可以使用相同的選擇器服務(wù)來引用結(jié)構(gòu)體的字段雁刷。

匿名字段和內(nèi)嵌結(jié)構(gòu)體
結(jié)構(gòu)體可以包含一個(gè)或多個(gè)匿名(或者稱為內(nèi)嵌)字段覆劈,即這些字段沒有顯式的名字。僅指明字段的類型沛励,此時(shí)該類型就是字段的名字责语。匿名字段本身可以是一個(gè)結(jié)構(gòu)體類型,即結(jié)構(gòu)體可以包含內(nèi)嵌的結(jié)構(gòu)體目派。

匿名字段
匿名字段和面向?qū)ο缶幊讨械睦^承概念相似坤候,可以被用來模擬類似繼承的行為。Golang 中的基礎(chǔ)就是通過內(nèi)嵌或組合來實(shí)現(xiàn)的企蹭,所以說在 Golang 中組合比繼承更受歡迎白筹。比如下面的例子:

type test struct {
name string
age int
int // 匿名字段
}
內(nèi)嵌結(jié)構(gòu)體
結(jié)構(gòu)體也是一種數(shù)據(jù)類型,所以它同樣可以作為匿名字段使用:

復(fù)制代碼
type Person struct {
Name string
Age int
Email string
}
type Student struct {
Person
StudentID int
}
復(fù)制代碼
下面的代碼可以聲明并初始化 Student 類型的變量:

st := Student {
Person: Person{"jack", 22, "jack@xxx.com"},
StudentID: 1000,
}
從這個(gè)示例可以看出谅摄,內(nèi)層結(jié)構(gòu)體被簡(jiǎn)單地插入或者內(nèi)嵌進(jìn)外層結(jié)構(gòu)體徒河。這種簡(jiǎn)單的 "繼承" 機(jī)制使得 Golang 很輕松就能實(shí)現(xiàn)從一個(gè)或一些類型中繼承部分或全部的實(shí)現(xiàn)。

總結(jié)
Golang 中沒有類的概念送漠,因此在 Golang 中結(jié)構(gòu)體有著更為重要的地位顽照。所以學(xué)習(xí)并掌握結(jié)構(gòu)體是入門 Golang 的關(guān)鍵步驟。希望本文能夠幫助大家理解 Golang 結(jié)構(gòu)體的基本概念和用法闽寡。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末代兵,一起剝皮案震驚了整個(gè)濱河市尼酿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奢人,老刑警劉巖谓媒,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異何乎,居然都是意外死亡句惯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門支救,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抢野,“玉大人,你說我怎么就攤上這事各墨≈腹拢” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵贬堵,是天一觀的道長(zhǎng)恃轩。 經(jīng)常有香客問我,道長(zhǎng)黎做,這世上最難降的妖魔是什么叉跛? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮蒸殿,結(jié)果婚禮上筷厘,老公的妹妹穿的比我還像新娘。我一直安慰自己宏所,他們只是感情好酥艳,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著爬骤,像睡著了一般充石。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盖腕,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天赫冬,我揣著相機(jī)與錄音,去河邊找鬼溃列。 笑死劲厌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的听隐。 我是一名探鬼主播补鼻,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了风范?” 一聲冷哼從身側(cè)響起咨跌,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎硼婿,沒想到半個(gè)月后锌半,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寇漫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年刊殉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片州胳。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡记焊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出栓撞,到底是詐尸還是另有隱情遍膜,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布瓤湘,位于F島的核電站瓢颅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏弛说。R本人自食惡果不足惜惜索,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剃浇。 院中可真熱鬧,春花似錦猎物、人聲如沸虎囚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽淘讥。三九已至,卻和暖如春堤如,著一層夾襖步出監(jiān)牢的瞬間蒲列,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工搀罢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蝗岖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓榔至,卻偏偏與公主長(zhǎng)得像抵赢,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 結(jié)構(gòu)體 結(jié)構(gòu)體(struct)是用戶自定義的類型铅鲤,代表若干字段的集合划提。有時(shí)將多個(gè)數(shù)據(jù)看做一個(gè)整體要比單獨(dú)使用這些數(shù)...
    與蟒唯舞閱讀 923評(píng)論 0 2
  • 結(jié)構(gòu)體方法和接受者 在go中,沒有類的概念但是可以給類型(結(jié)構(gòu)體邢享、自定義類型)定義方法鹏往。所謂方法就是定義了接受者的...
    learninginto閱讀 286評(píng)論 0 4
  • ?一個(gè)結(jié)構(gòu)體類型可以包含若干個(gè)字段,也可以不包含任何字段骇塘∫谅模空結(jié)構(gòu)體可以關(guān)聯(lián)上一些方法,從而看成是函數(shù)的特殊版本绪爸。 ...
    one_zheng閱讀 880評(píng)論 0 1
  • 結(jié)構(gòu)體是一種聚合的數(shù)據(jù)類型,它是由一系列具有相同類型或不同類型的數(shù)據(jù)結(jié)構(gòu)組成的數(shù)據(jù)集合递惋。每個(gè)數(shù)據(jù)成為結(jié)構(gòu)體的成員柔滔。...
    水無寒閱讀 1,391評(píng)論 0 0
  • Go語言中沒有“類”的改變,不支持類的“繼承”等面向?qū)ο蟾拍钇妓洹o語言中通過結(jié)構(gòu)體的內(nèi)嵌再配合接口比面向?qū)ο蟾哂?..
    Cici冬雪閱讀 2,591評(píng)論 0 0