亚洲熟女综合色一区二区三区,亚洲精品中文字幕无码蜜桃,亚洲va欧美va日韩va成人网,亚洲av无码国产一区二区三区,亚洲精品无码久久久久久久

Go 語言中的 Map

本文介紹一種特殊的數(shù)據(jù)結(jié)構(gòu)。它是一種元素對的無序集合,每一個索引(key)對應(yīng)一個值(value),這種數(shù)據(jù)結(jié)構(gòu)在 Go 語言中被稱之為?map。map?是一種能夠通過索引(key)迅速找到值(value)的數(shù)據(jù)結(jié)構(gòu),所以也被稱為字典。在 Go 語言中因?yàn)榫€程安全問題,一共實(shí)現(xiàn)了兩種類型的 map,接下來我們每種都了解一下。

Tips:線程的知識會在Go語言的多線程中講解。

 

1. 無鎖的map

這種類型的 map 是線程不安全的 map,多個線程同時訪問這個類型的 map 的同一個變量時,會有讀寫沖突,會導(dǎo)致系統(tǒng)奔潰。所以一般在單線程程序中使用的較多。

 

1.1 map 的創(chuàng)建

map 的底層結(jié)構(gòu)也是一個指針,所以和變量不同,并不是聲明后立刻能夠使用。和切片相同,需要使用make()函數(shù)進(jìn)行初始化。在初始化之前為空,沒有零值。

代碼示例:

代碼塊
  • 1? package main
  • 2
  • 3? import (
  • 4? ? ? ? ? "fmt"
  • 5? )
  • 6
  • 7? func main() {
  • 8? ? ? ? ? var m map[string]string
  • 9? ? ? ? ? fmt.Println(m == nil)
  • 10? ? ? ? m = make(map[string]string)
  • 11? ? ? ? fmt.Println(m == nil)
  • 12? }
  • 第 8 行:聲明一個 key 為 string 類型,value 為 string 類型的 map 變量;
  • 第 9 行:此時 m 未初始化,值為 nil;
  • 第 10 行:初始化 m。
  • 第 11 行:此時 m 是一個沒有存放數(shù)據(jù)的 map,值不為 nil。

執(zhí)行結(jié)果:

圖片描述

 

1.2 map 的賦值

map 的賦值有兩種方式:

  • 使用:=使map在定義的時候直接賦值;
  • 使用map[key]=value的形式對map進(jìn)行賦值。

在明確知道 map 的值的時候就可以使用第一種方式進(jìn)行賦值,比如說在建立中英文對應(yīng)關(guān)系的時候。在未知 map 的取值時,一般建議使用后者進(jìn)行賦值。

代碼示例:

代碼塊
  • 1? package main
  • 2
  • 3? import "fmt"
  • 4
  • 5? func main() {
  • 6? ? ? ? ? m1 := map[string]string{"Apple": "蘋果", "Orange": "橘子", "Banana": "香蕉"}
  • 7? ? ? ? ? fmt.Println(m1["Apple"])
  • 8? ? ? ? ? m2 := make(map[string]string)
  • 9? ? ? ? ? m2["Apple"] = "蘋果"
  • 10? ? ? ? m2["Orange"] = "橘子"
  • 11? ? ? ? m2["Banana"] = "香蕉"
  • 12? ? ? ? fmt.Println(m2["Apple"])
  • 13? }
  • 第 6 行:在 m1 被定義的時候直接賦值;
  • 第 7 行:輸出 m 1中 key 為 “Apple” 時對應(yīng)的值;
  • 第 8 行:使用:=進(jìn)行免聲明 make;
  • 第 9~11 行:對 m2 進(jìn)行賦值;
  • 第 12 行:輸出 m2 中 key 為 “Apple” 時對應(yīng)的值。

執(zhí)行結(jié)果:

圖片描述

 

1.3 map 的遍歷

map 是字典結(jié)構(gòu),如果不清楚所有 key 的值,是無法對 map 進(jìn)行遍歷的,所以 Go 語言中使用了一個叫做range的關(guān)鍵字,配合for循環(huán)結(jié)構(gòu)來對map結(jié)構(gòu)進(jìn)行遍歷。

Tips:range同時也可以用來遍歷數(shù)組和切片,數(shù)組和切片在range中可以看為map[int]數(shù)據(jù)類型結(jié)構(gòu),遍歷和用法和map一致。

代碼示例:

代碼塊
  • 1? package main
  • 2
  • 3? import "fmt"
  • 4
  • 5? func main() {
  • 6? ? ? ? ? m := map[string]string{"Apple": "蘋果", "Orange": "橘子", "Banana": "香蕉"}
  • 7? ? ? ? ? for k, v := range m {
  • 8? ? ? ? ? ? ? ? ? ? fmt.Println("key:", k, ", value:", v)
  • 9? ? ? ? ? }
  • 10? }
  • 第 7 行:使用 range 關(guān)鍵字,每次 for 循環(huán)都會取出一個不重復(fù)的 key 和 value,賦值給 k 和 v,直至循環(huán)結(jié)束。

Tips:map 是無序的,所以每次輸出的順序可能會不一樣。

執(zhí)行結(jié)果:

圖片描述

 

1.4 map 的刪除

map 在普通的用法中是無法移除只可以增加 key 和 value 的,所以 Go 語言中使用了一個內(nèi)置函數(shù)delete(map,key)來移除 map 中的 key 和 value。

代碼示例:

代碼塊
  • 1? package main
  • 2
  • 3? import "fmt"
  • 4
  • 5? func main() {
  • 6? ? ? ? ? ? m := map[string]string{"Apple": "蘋果", "Orange": "橘子", "Banana": "香蕉"}
  • 7? ? ? ? ? ? fmt.Println(m)
  • 8? ? ? ? ? ? delete(m, "Apple")
  • 9? ? ? ? ? ? fmt.Println(m)
  • 10? }
  • 第8行:刪除 m 中的 “Apple” 和其對應(yīng)的 value。

執(zhí)行結(jié)果:

圖片描述

 

2. 自帶鎖的 sync.Map

這種類型的 map 是線程安全的 map,多個線程同時訪問這個類型的 map 的同一個變量時,不會有讀寫沖突,因?yàn)樗詭г渔i,保障了多線程的數(shù)據(jù)安全。

 

2.1 sync.Map 的創(chuàng)建

這種類型的 map 創(chuàng)建不需要make,直接聲明就可以使用,而且不需要聲明 map 的 key 和 value 的類型。因?yàn)樗讓拥膶?shí)現(xiàn)并不是指針,是一種多個變量的聚合類型,叫做結(jié)構(gòu)體。

Tips:結(jié)構(gòu)體的概念會在Go語言的結(jié)構(gòu)體中講解

代碼示例:

代碼塊
  • 1? package main
  • 2
  • 3? import (
  • 4? ? ? ? ? "fmt"
  • 5? ? ? ? ? "sync"
  • 6? )
  • 7
  • 8 ?func main() {
  • 9? ? ? ? ? var m sync.Map
  • 10? ? ? ? fmt.Println(m)
  • 11? }
  • 第 9 行:聲明一個 sync.Map。
  • 第 10 行:輸出 m 的零值。

執(zhí)行結(jié)果:

圖片描述

 

2.2 sync.Map 的操作

這個類型關(guān)于 map 的所有操作都是使用它自帶的方法來實(shí)現(xiàn)的。包括range。

代碼示例:

代碼塊
  • 1? package main
  • 2
  • 3? import (
  • 4? ? ? ? ? "fmt"
  • 5? ? ? ? ? "sync"
  • 6? )
  • 7
  • 8? func main() {
  • 9
  • 10? ? ? ? var m sync.Map
  • 11? ? ? ? m.Store("Apple", "蘋果")
  • 12? ? ? ? m.Store("Orange", "橘子")
  • 13? ? ? ? m.Store("Banana", "香蕉")
  • 14? ? ? ? tmp, exist := m.Load("Orange")
  • 15? ? ? ? fmt.Println(tmp, exist)
  • 16
  • 17? ? ? ? m.Delete("Banana")
  • 18
  • 19? ? ? ? m.Range(func(k, v interface{}) bool {
  • 20? ? ? ? ? ? ? ?fmt.Println("key:", k, ", value:", v)
  • 21? ? ? ? ? ? ? ?return true
  • 22? ? ? ? })
  • 23? }
  • 第 11~13 行:使用 Store 方法給 m 賦值;
  • 第 14 行:使用 Load 取出 “Orange” 對應(yīng)的值,如果不存在 “Orange” 這個 key,exist 的值為 false;
  • 第 17 行:刪除 m 中的 “Banana” 和其對應(yīng)的 value;
  • 第 19 行:使用 Range 方法遍歷 m。

執(zhí)行結(jié)果:

圖片描述

 

3. 小結(jié)

本文主要講解了兩個 map 數(shù)據(jù)類型,兩種在功能上區(qū)別并不大,主要是在應(yīng)用上。map[數(shù)據(jù)類型]數(shù)據(jù)類型一般使用在單線程場景,多線程場景使用sync.Map。在賦值上map[數(shù)據(jù)類型]數(shù)據(jù)類型可以賦初值,且需要指定數(shù)據(jù)類型。sync.Map無法賦初值,無需指定數(shù)據(jù)類型。

文章來源于網(wǎng)絡(luò),侵刪!

相關(guān)新聞

歷經(jīng)多年發(fā)展,已成為國內(nèi)好評如潮的Linux云計算運(yùn)維、SRE、Devops、網(wǎng)絡(luò)安全、云原生、Go、Python開發(fā)專業(yè)人才培訓(xùn)機(jī)構(gòu)!