go——結構體(二)
Go語言是一種靜態型別的程式語言。這意味著,編譯器需要在編譯時知曉程式裡每個值的型別。
如果提前知道型別資訊,編譯器就可以確保程式合理的使用值。
這有助於減少潛在的記憶體異常和bug,並且使編譯器有機會對程式碼進行一些效能優化,提高執行效率。
值的型別給編譯器提供了兩部分資訊:第一部分,需要分配多少記憶體給這個值(即值得規模);第二部分,這段記憶體表示什麼。
對於許多內建型別的情況來說,規模和表示使型別名的一部分。
int64型別的值需要8位元組(64位),也可能是4位元組(32位)。
還有一些與體系結構相關的型別,如Go語言裡的所有引用型別。
Go語言允許使用者定義型別。當用戶宣告一個新型別時,這個宣告就給編譯器提供了一個框架,告知必要的記憶體大小和表示資訊。
聲明後的型別與內建型別的運作方式型別。
Go語言裡宣告使用者定義的型別有兩種方法。最常用的方法是使用關鍵字struct,它可以讓使用者建立一個結構型別。
結構型別通過組合一系列固定且唯一的欄位來宣告。
結構裡每個欄位都會用一個已知型別宣告。這個已知型別可以是內建型別,也可以是其它使用者定義的型別。
示例1:宣告一個結構型別
//user在程式裡定義一個使用者型別 type user struct { name string email string ext int privileged bool }
這個宣告以關鍵字type開始,之後是新型別的名字,最後是關鍵字struct。
這個結構型別有4個欄位,每個欄位都基於內建型別。一旦聲明瞭型別,就可以使用這個型別建立值。
示例2:使用結構型別宣告變數,並初始化其零值。
//宣告user型別的變數 var bill user
關鍵字var建立了型別為user且名為bill的變數。當宣告變數時,這個變數對應的值總是會被初始化。
這個值要麼用指定的值初始化,要麼用零值(即變數型別的預設值)做初始化。
對數值型別來說,零值是0;對字串來說,零值是字串;對布林型別,零值是false。
任何時候,建立一個變數並初始化為其零值,習慣是使用關鍵字var。這種用法是為了更明確地表示一個變數被設定為零值。
如果變數被初始化為某個非零值,就配合結構字面量和短變數宣告操作符來建立變數。
結構體字面量可以對結構型別採用兩種方式。
第一種方式:在不同行宣告每個欄位的名字以及對應的值,欄位名與值用冒號分隔,每一行以逗號結尾,這種形式對欄位的宣告順序沒有要求。
第二種方式:沒有欄位名,只宣告對應的值,值得順序很重要,可以寫在一行,也可以每個值分別佔一行。
示例3:使用結構字面量來表明一個結構型別的變數
//宣告user型別的變數,並初始化所有欄位 lisa := user{ name: "lisa", email: "[email protected]", ext: 123, privileged: true, }
示例4:不使用欄位名,建立結構型別得值。
//宣告user型別得變數 lisa := user{"lisa", "[email protected]", 123, "true"}
當宣告結構型別時,欄位的型別並不限制在內建型別,也可以使用自定義的型別。
示例5:使用其它結構型別宣告欄位
//admin需要一個user型別作為管理者,並附加許可權 type admin struct { person user level string }
為了初始化person欄位,我們需要建立一個user型別的值。
示例6:使用結構字面量來建立欄位的值
//宣告admin型別的變數 fred := admin{ person: user{ name: "lisa", email: "[email protected]", ext: 123, privileged: true, }, level: "super" }
另一種宣告使用者定義的型別的方法是,基於一個已有的型別,將其作為新型別的型別說明。
當需要一個可以用於已有型別表示的新型別的時候,這種方法會非常好用。
示例7:基於int64宣告一個新型別
type Duration int64
上面的這段自定義是標準庫time包裡的一個型別宣告。
Duration是一種描述時間間隔的型別,單位是納秒(ns)。這個型別使用內建的int64型別作為其表示。
在Duration型別的宣告中,我們把int64型別叫做Duration的基礎型別。
不過,雖然int64是基礎型別,Go並不認為Duration和int64是同一種類型。
兩種不同型別的值即使互相相容,也不能互相賦值。編譯器不會對不同型別的值做隱式轉換。