Go語言實戰筆記(六)| Go Map

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

《Go語言實戰》讀書筆記,未完待續,歡迎掃碼關注公眾號flysnow_org,第一時間看後續筆記。

書裡把Map翻譯為映射,我覺得太硬,所以這篇文章裡,我還是用英文Map。

Map是一種資料結構,是一個集合,用於儲存一系列無序的索引值對。它基於鍵儲存的,鍵就像一個索引一樣,這也是Map強大的地方,可以快速快速檢索資料,鍵指向與該鍵關聯的值。

內部實現

Map是給予散列表來實現,就是我們常說的Hash表,所以我們每次迭代Map的時候,列印的Key和Value是無序的,每次迭代的都不一樣,即使我們按照一定的順序存在也不行。

Map的散列表包含一組桶,每次儲存和尋找索引值對的時候,都要先選擇一個桶。如何選擇桶呢?就是把指定的鍵傳給散列函數,就可以索引到相應的桶了,進而找到對應的索引值。

這種方式的好處在於,儲存的資料越多,索引分布越均勻,所以我們訪問索引值對的速度也就越快,當然儲存的細節還有很多,大家可以參考Hash相關的知識,這裡我們只要記住Map儲存的是無序的索引值對集合

聲明和初始化

Map的建立有make函數,Map字面量。make函數我們用它建立過切片,除此之外,它還可以湧來建立Map。

1
dict:=make(map[string]int)

樣本中建立了一個鍵類型為string的,實值型別為int的map。現在建立好之後,這個map是空的,裡面什麼都沒有,我們給儲存一個索引值對。

12
dict := make(map[string]int)dict["張三"] = 43

儲存了一個Key為張三的,Value為43的索引值對資料。

此外還有一種使用map字面量的方式建立和初始化map,對於上面的例子,我們可以同等實現。

1
dict := map[string]int{"張三":43}

使用一個大括弧進行初始化,索引值對通過:分開,如果要同時初始化多個索引值對,使用逗號分割。

1
dict := map[string]int{"張三":43,"李四":50}

當然我們可以不指定任何索引值對,也就是一個空map。

1
dict := map[string]int{}

不管怎麼樣,使用map的字面量建立一定要帶上大括弧。如果我們要建立一個nil的Map怎麼做呢?nil的Map是未初始化的,所以我們可以只聲明一個變數,既不能使用map字面量,也不能使用make函數分配記憶體。

1
var dict map[string]int

這樣就好了,但是這樣我們是不能操作儲存索引值對的,必須要初始化後才可以,比如使用make函數,為其開啟一塊可以儲存資料的記憶體,也就是初始化。

1234
var dict map[string]intdict = make(map[string]int)dict["張三"] = 43fmt.Println(dict)

Map的鍵可以是任何值,鍵的類型可以是內建的類型,也可以是結構類型,但是不管怎麼樣,這個鍵可以使用==運算子進行比較,所以像切片、函數以及含有切片的結構類型就不能用於Map的鍵了,因為他們具有引用的語義,不可比較。

對於Map的值來說,就沒有什麼限制了,切片這種在鍵裡不能用的,完全可以用在值裡。

使用Map

Map的使用很簡單,和數組切片差不多,數組切片是使用索引,Map是通過鍵。

12
dict := make(map[string]int)dict["張三"] = 43

以上樣本,如果鍵張三存在,則對其值修改,如果不存在,則新增這個索引值對。

擷取一個Map鍵的值也很簡單,和儲存差不多,還是給予上面的例子。

1
age := dict["張三"]

在Go Map中,如果我們擷取一個不存在的鍵的值,也是可以的,返回的是實值型別的零值,這樣就會導致我們不知道是真的存在一個為零值的索引值對呢,還是說這個索引值對就不存在。對此,Map為我們提供了檢測一個索引值對是否存在的方法。

1
age,exists := dict["李四"]

看這個例子,和擷取鍵的值沒有太大區別,只是多了一個傳回值。第一個傳回值是鍵的值;第二個傳回值標記這個鍵是否存在,這是一個boolean類型的變數,我們判斷它就知道該鍵是否存在了。這也是Go多值返回的好處。

如果我們想刪除一個Map中的索引值對,可以使用Go內建的delete函數。

1
delete(dict,"張三")

delete函數接受兩個參數,第一個是要操作的Map,第二個是要刪除的Map的鍵。

delete函數刪除不存在的鍵也是可以的,只是沒有任何作用。

想要遍曆Map的話,可以使用for range風格的迴圈,和遍曆切片一樣。

1234
dict := map[string]int{"張三": 43}for key, value := range dict {fmt.Println(key, value)}

這裡的range 返回兩個值,第一個是Map的鍵,第二個是Map的鍵對應的值。這裡再次強調,這種遍曆是無序的,也就是索引值對不會按既定的資料出現,如果想安順序遍曆,可以先對Map中的鍵排序,然後遍曆排序好的鍵,把對應的值取出來,下面看個例子就明白了。

1234567891011
func main() {dict := map[string]int{"王五": 60, "張三": 43}var names []stringfor name := range dict {names = append(names, name)}sort.Strings(names) //排序for _, key := range names {fmt.Println(key, dict[key])}}

這個例子裡有個技巧,range 一個Map的時候,也可以使用一個傳回值,這個預設的傳回值就是Map的鍵。

在函數間傳遞Map

函數間傳遞Map是不會拷貝一個該Map的副本的,也就是說如果一個Map傳遞給一個函數,該函數對這個Map做了修改,那麼這個Map的所有引用,都會感知到這個修改。

123456789
func main() {dict := map[string]int{"王五": 60, "張三": 43}modify(dict)fmt.Println(dict["張三"])}func modify(dict map[string]int) {dict["張三"] = 10}

上面這個例子輸出的結果是10,也就是說已經被函數給修改了,可以證明傳遞的並不是一個Map的副本。這個特性和切片是類似的,這樣就會更高,因為複製整個Map的代價太大了。

《Go語言實戰》讀書筆記,未完待續,歡迎掃碼關注公眾號flysnow_org,第一時間看後續筆記。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.