11 Go語言的映射——map

Go語言的映射——map

[TOC]數組

  • 相似其它語言中的哈希表或者字典,以key-value形式存儲數據
  • Key必須是支持==或!=比較運算的類型,不能夠是函數、map或slice;value 能夠是任意類型。
  • Map查找比線性搜索快不少,但比使用索引訪問數據的類型慢100倍
  • Map使用make()創 建,支持 := 這種簡寫方式
  • make(map[keyType]valueType, cap),cap表示容量,可省略
  • 超出容量時會自動擴容,但儘可能提供一個合理的初始值,預先申請內存,有助於提高性能
  • 使用len()獲取元素個數
  • 鍵值對不存在時自動添加,使用delete()刪除某鍵值對
  • 使用 for range 對map和slice進行迭代操做

Map介紹

go語言中的map是一種數據結構,用於存儲一些列無序的鍵值對。map是一個無序的集合,由於它底層是一個hash表(散列表)。map的鍵只要支持==或!=比較運算的類型均可以,可是不能夠是函數,map,slice等不能比較的。value能夠是任意的類型。數據結構

一、Map 的建立

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"}

二、使用映射

2.1爲映射賦值

// 建立一個空映射,用來存儲顏色以及顏色對應的十六進制代碼
colors:=map[string]string{}
// 將 Red 的代碼加入到映射
colors["Red"]="#da1337"

2.1 未初始化的map,賦值報錯,即 nil map

// 經過聲明映射建立一個 nil 映射
var colors map[string]string
// 將 Red 的代碼加入到映射
colors["Red"] = "#da1337"
Runtime Error:
panic: runtime error: assignment to entry in nil map

2.2 從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)
}

2.3 用range迭代map

// 建立一個映射,存儲顏色以及顏色對應的十六進制代碼
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

2.4 map中的delete函數

delete(map,key) 函數能夠從map中刪除指定key的鍵值對。這種方法只能用在映射存儲的值都是非零值的狀況對象

// 刪除鍵爲 Coral 的鍵值對
delete(colors, "Coral")
// 顯示映射裏的全部顏色
for key, value := range colors {
    fmt.Printf("Key: %s Value: %s\n", key, value)
}

2.5 map做爲參數傳遞

和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)
}

三、從map取出的value是一個拷貝,對其成員修改沒有意義

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" // 返回的是指針複製品。透過指針修改原對象是容許的。
相關文章
相關標籤/搜索