[TOC]數組
- 相似其它語言中的哈希表或者字典,以key-value形式存儲數據
- Key必須是支持==或!=比較運算的類型,不能夠是函數、map或slice;value 能夠是任意類型。
- Map查找比線性搜索快不少,但比使用索引訪問數據的類型慢100倍
- Map使用make()創 建,支持 := 這種簡寫方式
- make(map[keyType]valueType, cap),cap表示容量,可省略
- 超出容量時會自動擴容,但儘可能提供一個合理的初始值,預先申請內存,有助於提高性能
- 使用len()獲取元素個數
- 鍵值對不存在時自動添加,使用delete()刪除某鍵值對
- 使用 for range 對map和slice進行迭代操做
go語言中的map是一種數據結構,用於存儲一些列無序的鍵值對。map是一個無序的集合,由於它底層是一個hash表(散列表)。map的鍵只要支持==或!=比較運算的類型均可以,可是不能夠是函數,map,slice等不能比較的。value能夠是任意的類型。數據結構
1.1 使用make函數函數
// 建立一個映射,鍵的類型是 string,值的類型是 int dict := make(map[string]int)
make(map[keyType]valueType, cap),cap表示容量,能夠在建立的時候指定一個合理初始的容量大小,這樣就會申請一大塊內存,避免在後續使用中頻繁擴張浪費性能。好比:m := make(map[string]int, 1000)
性能
1.2 使用字面值建立設計
// 建立一個映射,鍵和值的類型都是 string // 使用兩個鍵值對初始化映射 dict := map[string]string{"Red": "#da1337", "Orange": "#e95a22"}
// 建立一個空映射,用來存儲顏色以及顏色對應的十六進制代碼 colors:=map[string]string{} // 將 Red 的代碼加入到映射 colors["Red"]="#da1337"
// 經過聲明映射建立一個 nil 映射 var colors map[string]string // 將 Red 的代碼加入到映射 colors["Red"] = "#da1337" Runtime Error: panic: runtime error: assignment to entry in nil map
因爲go的多返回值,map獲取值的時候,會返回值,和一個boolean的參數,表示成不成功,有沒有,對不對。指針
在 Go 語言裏,經過鍵來索引映射時,即使這個鍵不存在也總會返回一個值。在這種狀況下,返回的是該值對應的類型的零值。rest
// 獲取鍵 Blue 對應的值 value, exists := colors["Blue"]// 這個鍵存在嗎? if exists { fmt.Println(value) } //固然了也能夠直接用 類型的零值來判斷----是同樣的 // 獲取鍵 Blue 對應的值 value := colors["Blue"] // 這個鍵存在嗎? if value != "" { fmt.Println(value) }
// 建立一個映射,存儲顏色以及顏色對應的十六進制代碼 colors := map[string]string{ "AliceBlue": "#f0f8ff", "Coral": "#ff7F50", "DarkGray": "#a9a9a9", "ForestGreen": "#228b22", } // 顯示映射裏的全部顏色 for key, value := range colors { fmt.Printf("Key: %s Value: %s\n", key, value) } //
range迭代和數組、slice 都同樣,只不過這裏返回的是map的鍵值對,而array ,slice返回的是索引和值code
delete(map,key) 函數能夠從map中刪除指定key的鍵值對。這種方法只能用在映射存儲的值都是非零值的狀況對象
// 刪除鍵爲 Coral 的鍵值對 delete(colors, "Coral") // 顯示映射裏的全部顏色 for key, value := range colors { fmt.Printf("Key: %s Value: %s\n", key, value) }
和slice同樣,都是引用類型,都是指向了底層數據結構。slice指向的是數組,map指向的是hash表。map在函數之間做爲參數傳遞的時候,是進行map指針的拷貝,相對於指針來講是值拷貝,相對於底層來講是引用傳遞。 其實我以爲go全部的傳遞都是值傳遞,只不過有的值是值,有的值是指針。索引
因此,在函數中傳遞map,對map進行修改會對底層數據進行修改。
// removeColor 將指定映射裏的鍵刪除 func removeColor(colors map[string]string, key string) { delete(colors, key) }
// 建立一個映射,存儲顏色以及顏色對應的十六進制代碼 colors := map[string]string{ "AliceBlue": "#f0f8ff", "Coral": "#ff7F50", "DarkGray": "#a9a9a9", "ForestGreen": "#228b22", } // 顯示映射裏的全部顏色 for key, value := range colors { fmt.Printf("Key: %s Value: %s\n", key, value) } fmt.Println() // 調用函數來移除指定的鍵 removeColor(colors, "Coral") // 顯示映射裏的全部顏色 for key, value := range colors { fmt.Printf("Key: %s Value: %s\n", key, value) } //輸出結果 Key: AliceBlue Value: #F0F8FF Key: Coral Value: #FF7F50 Key: DarkGray Value: #A9A9A9 Key: ForestGreen Value: #228B22 Key: AliceBlue Value: #F0F8FF Key: DarkGray Value: #A9A9A9 Key: ForestGreen Value: #228B22
map的常見操做
m := map[string]int{ "a": 1, } if v, ok := m["a"]; ok { // 判斷 key 是否存在。 println(v) } println(m["c"]) // 對於不存在的 key,直接返回 \0,不會出錯。 m["b"] = 2 // 新增或修改。 delete(m, "c") // 刪除。若是 key 不存在,不會出錯。 println(len(m)) // 獲取鍵值對數量。 cap ⽆效。 for k, v := range m { // 迭代,可僅返回 key。隨機順序返回,每次都不相同。 println(k, v) }
type user struct{ name string } m := map[int]user{ // 當 map 因擴張⽽從新哈希時,各鍵值項存儲位置都會發⽣改變。 所以, map 1: {"user1"}, // 被設計成 not addressable。 相似 m[1].name 這種指望透過原 value } // 指針修改爲員的⾏爲⾃然會被禁⽌。 m[1].name = "Tom" // Error: cannot assign to m[1].name
由於取出的是一個user實例的拷貝,不能直接對其成員修改,若是要實現,能夠有兩種方式
3.1完整的替換這個value
u := m[1] u.name = "Tom" m[1] = u // 替換 value。
3.2 使用指針
m2 := map[int]*user{ 1: &user{"user1"}, } m2[1].name = "Jack" // 返回的是指針複製品。透過指針修改原對象是容許的。