Go語言的字典類型其實就是一個哈希表的特定實現。字典的鍵的類型是受限的,元素的類型能夠是任意類型。算法
典的
鍵-元素對
的增刪改查的操做,就是哈希表的映射過程。數組
以查找爲例:安全
哈希值一般是一個無符號的整數。一個哈希表會持有必定數量的哈希桶。併發
因爲鍵-元素對老是被捆綁在一塊兒存儲的,因此一旦找到了鍵,就必定能找到對應的元素值。函數
回答:字典的鍵不能是函數類型,字典類型,切片類型。性能
那麼,剩下的:基本數據類型,(int系列,float系列,string,複數),數組,結構體,指針,接口等均可以做爲鍵類型。ui
Go語言規範規定:在鍵類型的值之間必須能夠施加操做符==
和!=
。也就是說鍵類型的值必需要支持判等操做。指針
求哈希和判等的速度越快,對應的類型就越適合做爲鍵類型。code
寬度越小的類型求哈希的速度一般越快。好比布爾類型,整數類型,浮點數類型,複數類型和指針類型。接口
對於字符串類型,因爲它的寬度是不定的,因此要看它的值的具體長度,長度越短,求哈希越快
類型的寬度是指它的單個值須要佔用的字節數。好比,bool,int8,uint8類型的一個值須要佔用的字節都是1個。所以寬度就都是1。
對於高級類型:
數組:對數組求哈希其實是依次求得它的每一個元素的哈希值並進行合併,因此速度就取決於它的元素類型以及它的長度。
結構體:對結構體類型的值求哈希值實際上就是對它的全部字段求哈希值並進行合併。因此關鍵在於它的各個字段的類型和字段的數量。
接口:對於接口類型,具體的哈希算法由值的實際類型決定。
不建議使用高級數據類型做爲字典的鍵類型。優先選用數值類型和指針類型。一般狀況下類型的寬度越小越好。若是非要選擇字符串類型的話,最好對鍵值的長度進行額外的約束。
一個是由於對他們求哈希值和判等的速度較慢,還由於他們的值中存在變數。好比,改變數組中任意一個元素,數組的哈希值就變了。
雖然結構體能夠經過控制其中字段的訪問權限,來防止外界修改它。
把接口類型做爲鍵類型最危險。
因爲字典是引用類型,當咱們僅僅聲明而不初始化一個字典類型的變量的時候,這個變量的值就是nil。
對這個值爲nil的字典進行添加鍵-元素對,會引起錯誤。其餘操做沒有問題。
非原子操做須要加鎖,map操做不是併發安全的,map併發讀寫須要加鎖。
判斷一個操做是不是原子的,可使用go run race
命令作數據的競爭檢測。經過 sync.Map 或本身使用sync.RWMutex本身實現併發互斥邏輯