Golang學(xué)習(xí)筆記之集合(map)

Map 是一種無序的鍵值對(duì)的集合。Map 最重要的一點(diǎn)是通過 key 來快速檢索數(shù)據(jù),key 類似于索引,指向數(shù)據(jù)的值。
Map 是一種集合,所以我們可以像迭代數(shù)組和切片那樣迭代它。不過,Map 是無序的,我們無法決定它的返回順序,這是因?yàn)?Map 是使用 hash 表來實(shí)現(xiàn)的。

? 引?類型,哈希表。
? 鍵必須是?持相等運(yùn)算符 (==、 !=) 類型,?如 number、 string、pointer、 array、 struct,以及對(duì)應(yīng)的 interface。
? 值可以是任意類型,沒有限制。

?map 的 0 值為 nil。試圖給一個(gè) nil map 添加元素給會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。

一、申明和初始化

可以通過將鍵和值的類型傳遞給內(nèi)置函數(shù) make 來創(chuàng)建一個(gè) map。一般語法為:
make(map[KeyType]ValueType)。
例如:
personSalary := make(map[string]int)
上面的代碼創(chuàng)建了一個(gè)名為 personSalary 的 map。其中鍵的類型為 string,值的類型為 int。

初始化
    mymap := make(map[string]string)
    mymap["name"] = "張三"
    mymap["professional"] = "全棧"
    fmt.Println(mymap)

方式二

var m map[string]int = map[string]int{"id":12,"age":20}

二、map的新增和修改

map通過鍵值的方式進(jìn)行新增,修改也是通過鍵

    mymap := make(map[string]string)
    mymap["name"] = "張三"
    mymap["professional"] = "全棧" //給map添加professional健
    fmt.Println(mymap)           //map[name:張三 professional:全棧]
    mymap["professional"] = "后臺(tái)" //修改professional鍵對(duì)應(yīng)的值
    fmt.Println(mymap)           //map[name:張三 professional:后臺(tái)]

三、訪問map元素,map通過鍵獲取值

    fmt.Println(mymap["name"])   //張三

四、map可以通過len來獲取長(zhǎng)度,cap無效

    fmt.Println(len(mymap))      //2

五、刪除元素,delete() 函數(shù)用于刪除集合的元素, 參數(shù)為 map 和其對(duì)應(yīng)的 key。

    delete(mymap, "name")
    fmt.Println(mymap) //map[professional:后臺(tái)]

六、判斷key是否存在

value, ok := map[key]
上面的語法可以檢測(cè)一個(gè)特定的鍵是否存在于 map 中。如果 ok 是true,則鍵存在,value 被賦值為對(duì)應(yīng)的值。如果 ok 為 false,則表示鍵不存在。

    value, ok := mymap["name"]
    fmt.Println(value, ok) //張三 true

七、遍歷。range for 可用于遍歷 map 中所有的元素

    for k, v := range mymap { // 迭代,可僅返回 key。隨機(jī)順序返回,每次都不相同。
        println(k, v)
    }

從 map 中取回的是?個(gè) value 臨時(shí)復(fù)制品,對(duì)其成員的修改是沒有任何意義的。
可以在迭代時(shí)安全刪除鍵值。

for k, v := range mymap { // 迭代,可僅返回 key。隨機(jī)順序返回,每次都不相同。
        println(k, v)
        delete(mymap,k)
    }

八、比較 map,map 不能通過 == 操作符比較是否相等。== 操作符只能用來檢測(cè)map 是否為 nil。

下面寫了一個(gè)比較map的函數(shù)

//判斷兩個(gè)map是否相等
func comparisonMap(map1 ,map2 map[string]string) bool {
    //判斷長(zhǎng)度
    if len(map1) != len(map2) {
        return false
    }
    //判斷值
    for key, value := range map1 {
        if value !=map2[key] {
            return false
        }
    }
    return true
}

九、線程安全

在很多時(shí)候,我們會(huì)并發(fā)地使用map對(duì)象,尤其是在一定規(guī)模的項(xiàng)目中,map總會(huì)保存goroutine共享的數(shù)據(jù)。在Go官方blog的Go maps in action一文中,提供了一種簡(jiǎn)便的解決方案。
地址https://blog.golang.org/go-maps-in-action需要翻墻

var counter = struct{
    sync.RWMutex
    m map[string]int
}{m: make(map[string]int)}

嵌入一個(gè)結(jié)構(gòu)體為map增加一個(gè)讀寫鎖。
讀數(shù)據(jù)的時(shí)候很方便的加鎖:

counter.RLock()
n := counter.m["some_key"]
counter.RUnlock()
fmt.Println("some_key:", n)

寫數(shù)據(jù)的時(shí)候,寫鎖

counter.Lock()
counter.m["some_key"]++
counter.Unlock()

示例

type MyMap struct {
    v map[string]string
    sync.RWMutex
}

func (this *MyMap) Put(key string, value string) {
    this.Lock()
    defer this.Unlock()
    this.v[key] = value
}
func (this *MyMap) Get(key string) string {
    this.RLock()
    defer this.RUnlock()
    return this.v[key]
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容