理解 Go 語言中的組合字面量(Composite Literal)
大家好我是 Go 學堂的漁夫子。前段時間在工作中,使用 go 的 struct 中的初始化時,由於在未指定的 key 的情況,有幾個欄位沒有賦值,導致編譯錯誤。所以才有了下面這篇文章。
什麼是 Composite Literal
首先看下 Go 文件中對 Composite Literal 的定義:
Composite literals construct values for structs, arrays, slices, and maps and create a new value each time they are evaluated. They consist of the type of the literal followed by a brace-bound list of elements. Each element may optionally be preceded by a corresponding key。
翻譯成中文大致如下: 組合字面量是為結構體、陣列、切片和 map 構造值,並且每次都會建立新值。它們由字面量的型別後緊跟大括號及元素列表。每個元素前面可以選擇性的帶一個相關 key。
什麼意思呢?所謂的組合字面量其實就是把變數的定義和變數的初始化放在一起了。
接下來讓我們看看結構體、陣列、切片和 map 各自的常規方式和組合字面量方式。
結構體的定義和初始化:常規方式 VS 組合字面量方式
讓我們看一個 struct 結構體的常規的定義和初始化是怎麼樣的。
- 常規方式 ```golang //定義結構體 type location struct { lat float64 long float64 }
//宣告變數 var loc location
//變數賦值 opportunity.lat = -1.9462 opportunity.long = 354.4734
常規方式這樣定義是逐一欄位賦值,這樣就比較繁瑣。
- **組合字面量方式**
```golang
//定義結構體
type location struct {
lat float64
long float64
}
//宣告且初始化變數
var loc location = {lat: -1.9462, long: 354.4734}
//短語法方式
loc2 := location{lat: -1.9462, long:354.4734}
//不指定key的方式
loc3 := location{-1.9462, 354.4734}
在該示例中,我們看到在初始化變數時可以指定結構體的 key,也可以不指定結構體的 key 兩種方式。下面我們看看這兩種方式各自的特點。
-
指定結構體 key 的方式:
- 該方式是按指定的 key 值進行賦值,沒指定的 key 的值則預設為結構體中變數的零值
- key 的順序無關,如下面示例所示。
- 如果在結構體中有新增的欄位,那麼已初始化的變數中該欄位為預設型別的零值 ```golang //定義結構體 type location struct { lat float64 long float64 } //只給 lat 欄位賦值,long 欄位預設為 float64 的零值 0 loc := location{lat: -1.9462} //該例項中 long 欄位預設為 0
//跟 key 的順序無關 loc1 := location{long:354.4734, lat: -1.9462} loc2 := location{lat: -1.9462, long: 354.4734} fmt.Println(loc1 == loc2) //輸出 true
-
不指定結構體 key 的方式:
- 該方式是按結構體中定義的 key 順序依次賦值
- 結構體中的每個 key 都不必須進行顯式賦值
- 如果在賦值中,元素個數和結構體的 key 個數不匹配,則會報錯
- 如果結構體中增加了新欄位,則要在該結構體所有初始化的地方都需要補充上該欄位的值。
//定義結構體
type location struct {
lat float64
long float64
}
//不帶key的結構體初始化
loc := location{-1.9462, 354.4734} //-1.9462賦值給lat欄位,354.4734賦值給long欄位
loc2 := location{-1.9462} //編譯時會報錯 too few values in struct initializer
- 小結 在 struct 的組合字面量初始化時,推薦使用帶 key 的方式進行初始化,首先,更具有易讀性。可以不用關心結構體定義中的欄位順序,每個欄位的初始值很明確。其次,比 unkey 的方式更不容易出錯。在結構體中增加了新欄位後,已經初始化的程式碼中不會編譯出錯,預設是該欄位型別的零值。
陣列的定義和初始化:常規方式 VS 組合字面量方式
- 常規方式
var planets [8]string
planets[0] = "Mercury" //水星
planets[1] = "Venus" //金星
planets[2] = "Earth" //地球
在上面的程式碼中,我們在第 1 行定義了一個 8 個元素大小的字串陣列。然後一個一個的給元素賦值。即陣列變數的定義和初始化是分開的。
- 組合字面量方式
balls := [4]string{"basketball", "football", "Volleyball", "Tennis"}
該示例中,就是將變數 balls 的定義和初始化合並了在一起。
使用組合字面量語法初始化陣列時,還可以用三個點"..."來代替陣列元素的個數,Go 的編譯器在編譯時會根據初始化時指定的元素列表來自動計算元素個數。例如:
balls := [...]string{"basketball", "football", "volleyball", "Tennis"}
這樣的好處是不用顯式的指定元素個數,只有在編譯階段,編譯器才會根據列出來的元素列表確定個數。
slice 的定義和初始化
- 常規方式 ```golang var s [] string //定義切片變數 s,s 為預設零值 nil
s = append(s, "hat", "shirt") //往 s 中增加元素,len(s):2,cap(s):2
s := make([] string, 0, 10) //定義 s,s 的預設值不為零值
- **組合字面量方式**
由上面的常規方式可知,首先都是需要先定義切片,然後再往切片中新增元素。接下來我們看下組合字面量方式。
```golang
s := []string{"hat", "shirt"} //定義和初始化一步完成,自動計算切片的容量和長度
// or
var s = []string{"hat", "shirt"}
map 的定義和初始化
- 常規方式 ```golang //通過 make 函式初始化 m := make(map[string] int, 10) m["english"] = 99 m["math"] = 98
- **組合字面量方式**
```golang
m := map[string]int {
"english": 99,
"math": 98,
}
//組合字面量初始化多維map
m2 := map[string]map[int]string {
"english": {
10: "english",
},
}
顯然,使用組合字面量會比常規方式簡單了不少。
小結
組合字面量就是將結構體、陣列、切片、map 型別的變數定義和初始化放在一起。每次初始化的時候都是新定義一個變數值。尤其在使用 struct 型別的組合字面量時,可以使用指定 key 和不帶 key 的方式進行初始化,當然我們推薦使用帶 key 的初始化方式。
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- JavaScript 物件字面量(object literal)JavaScript物件Object
- 理解函數語言程式設計語言中的組合--前言(一)函數程式設計
- 組合模式(Composite)模式
- composite pattern(組合模式)模式
- 用“揹包”去理解Go語言中的閉包Go
- Go 語言中的方法Go
- Go 語言的組合之道Go
- Go 語言中的 collect 使用Go
- Go 語言中的 切片 --sliceGo
- Go 語言中的外掛Go
- Go語言的識別符號、關鍵字、字面量、型別Go符號型別
- GO 語言中的物件導向Go物件
- Go語言中的併發模式Go模式
- 《設計模式》 - 7. 組合模式( Composite )設計模式
- [C++設計模式] composite 組合模式C++設計模式
- 設計模式之組合模式(Composite)分享設計模式
- Go 語言中使用 ETCDGo
- Go語言中的變數作用域Go變數
- Go語言中的單元測試Go
- 認識 Go 語言中的陣列Go陣列
- C#設計模式-組合模式(Composite Pattern)C#設計模式
- Go 語言中的兩種 slice 表示式Go
- Go語言中defer的一些坑Go
- 9.Go語言中的流程控制Go
- Go 語言中的格式化輸出Go
- 詳細解讀go語言中的chnanelGoNaN
- 聊聊Go語言中的陣列與切片Go陣列
- Go語言中時間輪的實現Go
- hash 表在 go 語言中的實現Go
- C語言中continue的理解(fishing_1)C語言
- Go 語言中 strings 包常用方法Go
- go 語言中預設的型別識別Go型別
- Go語言中切片slice的宣告與使用Go
- Go語言中JSON標籤的用法與技巧GoJSON
- 在Go語言中,怎樣使用Json的方法?GoJSON
- go 語言中的 rune,獲取字元長度Go字元
- Go 語言中常見的幾種反模式Go模式
- Go語言中的加解密利器:go-crypto庫全解析Go解密