Go 經(jīng)典入門系列 12:Maps
歡迎來到 Golang 系列教程的第 13 個(gè)教程。
什么是 map ?
map 是在 Go 中將值(value)與鍵(key)關(guān)聯(lián)的內(nèi)置類型。通過相應(yīng)的鍵可以獲取到值。
如何創(chuàng)建 map ?
通過向 make 函數(shù)傳入鍵和值的類型,可以創(chuàng)建 map。make(map[type of key]type of value) 是創(chuàng)建 map 的語法。
personSalary?:=?make(map[string]int)
上面的代碼創(chuàng)建了一個(gè)名為 personSalary 的 map,其中鍵是 string 類型,而值是 int 類型。
map 的零值是 nil。如果你想添加元素到 nil map 中,會(huì)觸發(fā)運(yùn)行時(shí) panic。因此 map 必須使用 make 函數(shù)初始化。
package?main
import?(
?"fmt"
)
func?main()?{
?var?personSalary?map[string]int
?if?personSalary?==?nil?{
??fmt.Println("map?is?nil.?Going?to?make?one.")
??personSalary?=?make(map[string]int)
?}
}
在線運(yùn)行程序[1]
上面的程序中,personSalary 是 nil,因此需要使用 make 方法初始化,程序?qū)⑤敵?map is nil. Going to make one.。
給 map 添加元素
給 map 添加新元素的語法和數(shù)組相同。下面的程序給 personSalary map 添加了幾個(gè)新元素。
package?main
import?(
?"fmt"
)
func?main()?{
?personSalary?:=?make(map[string]int)
?personSalary["steve"]?=?12000
?personSalary["jamie"]?=?15000
?personSalary["mike"]?=?9000
?fmt.Println("personSalary?map?contents:",?personSalary)
}
在線運(yùn)行程序[2]
上面的程序輸出:personSalary map contents: map[steve:12000 jamie:15000 mike:9000]
你也可以在聲明的時(shí)候初始化 map。
package?main
import?(
?"fmt"
)
func?main()?{
?personSalary?:=?map[string]int?{
??"steve":?12000,
??"jamie":?15000,
?}
?personSalary["mike"]?=?9000
?fmt.Println("personSalary?map?contents:",?personSalary)
}
在線運(yùn)行程序[3]
上面的程序聲明了 personSalary,并在聲明的同時(shí)添加兩個(gè)元素。之后又添加了鍵 mike。程序輸出:
personSalary?map?contents:?map[steve:12000?jamie:15000?mike:9000]
鍵不一定只能是 string 類型。所有可比較的類型,如 boolean,interger,float,complex,string 等,都可以作為鍵。關(guān)于可比較的類型,如果你想了解更多,請?jiān)L問 http://golang.org/ref/spec#Comparison_operators[4]。
獲取 map 中的元素
目前我們已經(jīng)給 map 添加了幾個(gè)元素,現(xiàn)在學(xué)習(xí)下如何獲取它們。獲取 map 元素的語法是 map[key] 。
package?main
import?(
?"fmt"
)
func?main()?{
?personSalary?:=?map[string]int{
??"steve":?12000,
??"jamie":?15000,
?}
?personSalary["mike"]?=?9000
?employee?:=?"jamie"
?fmt.Println("Salary?of",?employee,?"is",?personSalary[employee])
}
在線運(yùn)行程序[5]
上面的程序很簡單。獲取并打印員工 jamie 的薪資。程序輸出 Salary of jamie is 15000。
如果獲取一個(gè)不存在的元素,會(huì)發(fā)生什么呢?map 會(huì)返回該元素類型的零值。在 personSalary 這個(gè) map 里,如果我們獲取一個(gè)不存在的元素,會(huì)返回 int 類型的零值 0。
package?main
import?(
?"fmt"
)
func?main()?{
?personSalary?:=?map[string]int{
??"steve":?12000,
??"jamie":?15000,
?}
?personSalary["mike"]?=?9000
?employee?:=?"jamie"
?fmt.Println("Salary?of",?employee,?"is",?personSalary[employee])
?fmt.Println("Salary?of?joe?is",?personSalary["joe"])
}
在線運(yùn)行程序[6]
上面程序輸出:
Salary?of?jamie?is?15000
Salary?of?joe?is?0
上面程序返回 joe 的薪資是 0。personSalary 中不包含 joe 的情況下我們不會(huì)獲取到任何運(yùn)行時(shí)錯(cuò)誤。
如果我們想知道 map 中到底是不是存在這個(gè) key,該怎么做:
value,?ok?:=?map[key]
上面就是獲取 map 中某個(gè) key 是否存在的語法。如果 ok 是 true,表示 key 存在,key 對應(yīng)的值就是 value ,反之表示 key 不存在。
package?main
import?(
?"fmt"
)
func?main()?{
?personSalary?:=?map[string]int{
??"steve":?12000,
??"jamie":?15000,
?}
?personSalary["mike"]?=?9000
?newEmp?:=?"joe"
?value,?ok?:=?personSalary[newEmp]
?if?ok?==?true?{
??fmt.Println("Salary?of",?newEmp,?"is",?value)
?}?else?{
??fmt.Println(newEmp,"not?found")
?}
}
在線運(yùn)行程序[7]
上面的程序中,第 15 行,joe 不存在,所以 ok 是 false。程序?qū)⑤敵觯?/p>
joe?not?found
遍歷 map 中所有的元素需要用 for range 循環(huán)。
package?main
import?(
?"fmt"
)
func?main()?{
?personSalary?:=?map[string]int{
??"steve":?12000,
??"jamie":?15000,
?}
?personSalary["mike"]?=?9000
?fmt.Println("All?items?of?a?map")
?for?key,?value?:=?range?personSalary?{
??fmt.Printf("personSalary[%s]?=?%d\n",?key,?value)
?}
}
在線運(yùn)行程序[8]
上面程序輸出:
All?items?of?a?map
personSalary[mike]?=?9000
personSalary[steve]?=?12000
personSalary[jamie]?=?15000
有一點(diǎn)很重要,當(dāng)使用 for range 遍歷 map 時(shí),不保證每次執(zhí)行程序獲取的元素順序相同。
刪除 map 中的元素
刪除 map 中 key 的語法是 _delete(map, key)_[9]。這個(gè)函數(shù)沒有返回值。
package?main
import?(
?"fmt"
)
func?main()?{
?personSalary?:=?map[string]int{
??"steve":?12000,
??"jamie":?15000,
?}
?personSalary["mike"]?=?9000
?fmt.Println("map?before?deletion",?personSalary)
?delete(personSalary,?"steve")
?fmt.Println("map?after?deletion",?personSalary)
}
在線運(yùn)行程序[10]
上述程序刪除了鍵 "steve",輸出:
map?before?deletion?map[steve:12000?jamie:15000?mike:9000]
map?after?deletion?map[mike:9000?jamie:15000]
獲取 map 的長度
獲取 map 的長度使用 len[11] 函數(shù)。
package?main
import?(
?"fmt"
)
func?main()?{
?personSalary?:=?map[string]int{
??"steve":?12000,
??"jamie":?15000,
?}
?personSalary["mike"]?=?9000
?fmt.Println("length?is",?len(personSalary))
}
在線運(yùn)行程序[12]
上述程序中的 len(personSalary) 函數(shù)獲取了 map 的長度。程序輸出 length is 3。
Map 是引用類型
和 slices[13] 類似,map 也是引用類型。當(dāng) map 被賦值為一個(gè)新變量的時(shí)候,它們指向同一個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu)。因此,改變其中一個(gè)變量,就會(huì)影響到另一變量。
package?main
import?(
?"fmt"
)
func?main()?{
?personSalary?:=?map[string]int{
??"steve":?12000,
??"jamie":?15000,
?}
?personSalary["mike"]?=?9000
?fmt.Println("Original?person?salary",?personSalary)
?newPersonSalary?:=?personSalary
?newPersonSalary["mike"]?=?18000
?fmt.Println("Person?salary?changed",?personSalary)
}
在線運(yùn)行程序[14]
上面程序中的第 14 行,personSalary 被賦值給 newPersonSalary。下一行 ,newPersonSalary 中 mike 的薪資變成了 18000 。personSalary 中 Mike 的薪資也會(huì)變成 18000。程序輸出:
Original?person?salary?map[steve:12000?jamie:15000?mike:9000]
Person?salary?changed?map[steve:12000?jamie:15000?mike:18000]
當(dāng) map 作為函數(shù)參數(shù)傳遞時(shí)也會(huì)發(fā)生同樣的情況。函數(shù)中對 map 的任何修改,對于外部的調(diào)用都是可見的。
Map 的相等性
map 之間不能使用 == 操作符判斷,== 只能用來檢查 map 是否為 nil。
package?main
func?main()?{
?map1?:=?map[string]int{
??"one":?1,
??"two":?2,
?}
?map2?:=?map1
?if?map1?==?map2?{
?}
}
在線運(yùn)行程序[15]
上面程序拋出編譯錯(cuò)誤 invalid operation: map1 == map2 (map can only be compared to nil)。
判斷兩個(gè) map 是否相等的方法是遍歷比較兩個(gè) map 中的每個(gè)元素。我建議你寫一段這樣的程序?qū)崿F(xiàn)這個(gè)功能 :)。
我在一個(gè)程序里實(shí)現(xiàn)了我們討論過的所有概念。你可以從 github[16] 下載代碼。
這就是 map 。謝謝你的閱讀。祝好。
下一教程 - 字符串[17]
via: https://golangbot.com/maps/
作者:Nick Coghlan[18]譯者:ArisAries[19]校對:Noluye[20]
本文由 GCTT[21] 原創(chuàng)編譯,Go 中文網(wǎng)[22] 榮譽(yù)推出
參考資料
在線運(yùn)行程序: https://play.golang.org/p/IwJnXMGc1M
[2]在線運(yùn)行程序: https://play.golang.org/p/V1lnQ4Igw1
[3]在線運(yùn)行程序: https://play.golang.org/p/nlH_ADhO9f
[4]http://golang.org/ref/spec#Comparison_operators: http://golang.org/ref/spec#Comparison_operators
[5]在線運(yùn)行程序: https://play.golang.org/p/-TSBac7F1v
[6]在線運(yùn)行程序: https://play.golang.org/p/EhUJhIkYJU
[7]在線運(yùn)行程序: https://play.golang.org/p/q8fL6MeVZs
[8]在線運(yùn)行程序: https://play.golang.org/p/gq9ZOKsI9b
[9]delete(map, key): https://golang.org/pkg/builtin/#delete
[10]在線運(yùn)行程序: https://play.golang.org/p/nroJzeF-a7
[11]len: https://golang.org/pkg/builtin/#len
[12]在線運(yùn)行程序: https://play.golang.org/p/8O1WnKUuDP
[13]slices: https://golangbot.com/arrays-and-slices/
[14]在線運(yùn)行程序: https://play.golang.org/p/OGFl3addq1
[15]在線運(yùn)行程序: https://play.golang.org/p/MALqDyWkcT
[16]github: https://github.com/golangbot/maps
[17]字符串: https://studygolang.com/articles/12261
[18]Nick Coghlan: https://golangbot.com/about/
[19]ArisAries: https://github.com/ArisAries
[20]Noluye: https://github.com/Noluye
[21]GCTT: https://github.com/studygolang/GCTT
[22]Go 中文網(wǎng): https://studygolang.com/
推薦閱讀
xxx
