欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

十個(gè)Go map面試常考問(wèn)題合集

 更新時(shí)間:2023年07月30日 17:11:34   作者:nil  
go面試中,map相關(guān)知識(shí)點(diǎn)問(wèn)的比較多,這篇文章主要為大家整理歸納了10個(gè)??嫉膯?wèn)題,文中的示例代碼講解詳細(xì),希望對(duì)大家有一定的幫助

1.Map 使用時(shí)需要注意哪些問(wèn)題

Map 的鍵必須是可比較的類型,如整數(shù)、字符串和指針等,但是切片、函數(shù)和結(jié)構(gòu)體等類型是不可比較的,因此不能用作鍵。

Map 中的元素是無(wú)序的,這意味著遍歷 Map 時(shí),元素的順序可能會(huì)隨機(jī)改變。

Map 的容量是動(dòng)態(tài)變化的,它會(huì)自動(dòng)調(diào)整容量以適應(yīng)新的元素。

如果使用未初始化的 Map,會(huì)導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。需要使用 make() 函數(shù)來(lái)初始化 Map。

Map 在并發(fā)環(huán)境下不是安全的。如果需要在并發(fā)環(huán)境下使用 Map,需要使用 sync 包中提供的鎖機(jī)制來(lái)保護(hù) Map。

2.Map 擴(kuò)容是怎么實(shí)現(xiàn)的

在 Go 中,Map 的內(nèi)部實(shí)現(xiàn)是基于哈希表(hash table)的,因此,當(dāng) Map 中的鍵值對(duì)數(shù)量增加時(shí),Map 會(huì)自動(dòng)擴(kuò)容以提供更多的存儲(chǔ)空間。下面是 Go Map 擴(kuò)容的具體步驟:

  • 當(dāng) Map 中的元素?cái)?shù)量超過(guò)了負(fù)載因子(load factor)和哈希表容量的乘積時(shí),map 就會(huì)觸發(fā)擴(kuò)容操作。在 Go 中,負(fù)載因子默認(rèn)為 6.5。
  • Go Map 在擴(kuò)容時(shí)會(huì)創(chuàng)建一個(gè)新的哈希表,并將原來(lái)的鍵值對(duì)重新散列到新的哈希表中。為了減少哈希沖突,新哈希表的容量是原來(lái)的兩倍,并且容量一定是 2 的冪次方。即每次擴(kuò)容按照規(guī)則計(jì)算出新容量之后,為了內(nèi)存對(duì)齊,減少內(nèi)存碎片,會(huì)根據(jù)一個(gè)常量數(shù)字進(jìn)行向上取整。
  • 在重新散列過(guò)程中,Go Map 會(huì)根據(jù)哈希值將原來(lái)的鍵值對(duì)分配到新哈希表中的對(duì)應(yīng)位置上。如果兩個(gè)鍵值對(duì)的哈希值相同,會(huì)使用鏈?zhǔn)焦1恚╟hained hash table)的方式進(jìn)行處理,將它們放在同一個(gè)桶(bucket)中。
  • 一旦所有的鍵值對(duì)都已經(jīng)重新散列到新的哈希表中,Go Map 就會(huì)將原來(lái)的哈希表釋放掉,將新的哈希表作為 Map 的內(nèi)部存儲(chǔ)結(jié)構(gòu)。

注意:  由于擴(kuò)容操作可能會(huì)導(dǎo)致大量的重新散列操作,因此在擴(kuò)容時(shí)可能會(huì)造成一定的性能影響。為了避免頻繁擴(kuò)容,可以在創(chuàng)建 Map 時(shí)指定一個(gè)較大的容量,或者手動(dòng)調(diào)用 runtime.GC()  來(lái)觸發(fā)垃圾回收操作,以釋放未使用的內(nèi)存。

3. Map 的 panic 能被 recover 嗎

不能,并發(fā)讀寫(xiě) Map 也是很容易遇到的問(wèn)題

if?h.flags&hashWriting?!=?0?{
??throw("concurrent?map?read?and?map?write")
}

runtime.throw() 函數(shù)拋出異常是無(wú)法recover的

4. 并發(fā)使用 Map 除了加鎖還有什么其他方案嗎

除了加鎖之外,Go 并發(fā)使用 Map 的其他常見(jiàn)解決方案包括使用 sync.Map 和使用并發(fā)安全的第三方 Map 庫(kù)。

1、使用 sync.Map sync.Map 是 Go 1.9 新增的一種并發(fā)安全的 Map,它的讀寫(xiě)操作都是并發(fā)安全的,無(wú)需加鎖。使用 sync.Map 的示例代碼如下:

var?m?sync.Map
m.Store("name",?"程序員祝融")
value,?ok?:=?m.Load("name")
if?ok?{
????fmt.Println(value)
}
//?輸出程序員祝融

2、使用并發(fā)安全的第三方 Map 庫(kù) 除了使用 sync.Map,還可以使用其他第三方的并發(fā)安全的 Map 庫(kù),如 concurrent-map、ccmap 等。這些庫(kù)的使用方式與 Go 標(biāo)準(zhǔn)庫(kù)的 Map 類似,但它們都提供了更高效、更可靠的并發(fā)安全保證。

注意:  使用并發(fā)安全的第三方 Map 庫(kù)可能會(huì)導(dǎo)致額外的依賴和復(fù)雜性,因此需要仔細(xì)評(píng)估是否值得使用

5. sync.Map 和加鎖的區(qū)別是什么

sync.Map 和使用鎖的區(qū)別在于,sync.Map 不需要在并發(fā)訪問(wèn)時(shí)進(jìn)行加鎖和解鎖操作。相比之下,使用鎖需要在并發(fā)訪問(wèn)時(shí)顯式地加鎖和解鎖,以避免競(jìng)爭(zhēng)條件和數(shù)據(jù)競(jìng)爭(zhēng)問(wèn)題。

在使用鎖時(shí),當(dāng)多個(gè) goroutine 同時(shí)訪問(wèn)同一塊數(shù)據(jù)時(shí),必須通過(guò)加鎖來(lái)避免競(jìng)爭(zhēng)條件。這意味著只有一個(gè) goroutine 能夠訪問(wèn)該數(shù)據(jù),并且在該 goroutine 完成工作后,其他 goroutine 才能夠訪問(wèn)數(shù)據(jù)。這種方式可以確保數(shù)據(jù)的一致性,但是加鎖會(huì)帶來(lái)額外的開(kāi)銷,并且在高并發(fā)情況下可能會(huì)影響性能。

相比之下,sync.Map 使用了更高級(jí)的算法來(lái)避免競(jìng)爭(zhēng)條件和數(shù)據(jù)競(jìng)爭(zhēng)問(wèn)題,而不需要顯式地進(jìn)行加鎖和解鎖。當(dāng)多個(gè) goroutine 同時(shí)訪問(wèn) sync.Map 時(shí),它會(huì)自動(dòng)分配不同的段來(lái)存儲(chǔ)數(shù)據(jù),并且每個(gè)段都有自己的讀寫(xiě)鎖,以避免競(jìng)爭(zhēng)條件。這種方式可以提高并發(fā)性能,減少開(kāi)銷,并且避免死鎖等問(wèn)題。

6. Map 的查詢時(shí)間復(fù)雜度

Go 中的 Map 底層實(shí)現(xiàn)采用了哈希表,因此其查詢時(shí)間復(fù)雜度為 O(1),最壞情況為 O(n)。

7. Map Rehash 的策略是怎樣的 什么時(shí)機(jī)會(huì)發(fā)生 Rehash

當(dāng)哈希表中的元素?cái)?shù)量達(dá)到一定閾值時(shí),就會(huì)觸發(fā)哈希表的擴(kuò)容操作,也就是進(jìn)行 rehash。

Go 標(biāo)準(zhǔn)庫(kù)中的哈希表實(shí)現(xiàn)在以下情況下會(huì)觸發(fā) rehash 操作:

  • 當(dāng)哈希表中的元素?cái)?shù)量超過(guò)了哈希表容量的 2/3 時(shí),會(huì)觸發(fā)擴(kuò)容操作。此時(shí),哈希表的容量會(huì)翻倍,并且哈希表中所有的元素都會(huì)重新哈希到新的槽位中。
  • 當(dāng)哈希表中的元素?cái)?shù)量過(guò)少,而哈希表的容量過(guò)大時(shí),會(huì)觸發(fā)收縮操作。此時(shí),哈希表的容量會(huì)減半,并且哈希表中所有的元素都會(huì)重新哈希到新的槽位中。
  • 當(dāng)哈希表的探測(cè)序列過(guò)長(zhǎng)時(shí),會(huì)觸發(fā)重排操作。此時(shí),哈希表中的元素不會(huì)重新哈希,但是它們的存儲(chǔ)位置會(huì)發(fā)生變化,從而減少聚簇現(xiàn)象,提高哈希表的性能。

在進(jìn)行 rehash 操作時(shí),哈希表會(huì)創(chuàng)建一個(gè)新的數(shù)組來(lái)存儲(chǔ)重新哈希后的元素,然后將舊數(shù)組中的元素逐個(gè)復(fù)制到新數(shù)組中。由于重新哈希的過(guò)程比較耗時(shí),因此 Go 標(biāo)準(zhǔn)庫(kù)中的哈希表實(shí)現(xiàn)采用了增量式 rehash 策略,在擴(kuò)容和收縮時(shí)只會(huì)處理一部分元素,避免一次性處理過(guò)多元素導(dǎo)致性能下降。具體來(lái)說(shuō),增量式 rehash 的策略是:

  • 將新數(shù)組的容量設(shè)置為舊數(shù)組的兩倍或一半,并且將哈希表的增量計(jì)數(shù)器加一。
  • 在對(duì)哈希表進(jìn)行操作時(shí),如果發(fā)現(xiàn)增量計(jì)數(shù)器的值達(dá)到了一個(gè)閾值,就會(huì)開(kāi)始進(jìn)行增量式 rehash 操作,將一部分元素從舊數(shù)組中復(fù)制到新數(shù)組中,并且重新計(jì)算這些元素的哈希值。
  • 在完成一次增量式 rehash 操作后,會(huì)將哈希表的增量計(jì)數(shù)器清零。

通過(guò)增量式 rehash 的策略,Go 標(biāo)準(zhǔn)庫(kù)中的哈希表實(shí)現(xiàn)可以在保證較短的 rehash 時(shí)間的同時(shí),避免一次性處理過(guò)多元素導(dǎo)致性能下降

8. Map Rehash 具體會(huì)影響什么?哈希結(jié)果會(huì)受到什么影響

rehash 操作會(huì)影響 Map 的性能。由于重新計(jì)算鍵的哈希值,rehash 操作會(huì)消耗一定的計(jì)算資源。此外,在 rehash 過(guò)程中,原始哈希表的所有鍵值對(duì)都需要復(fù)制到新的哈希表中,因此 rehash 操作還會(huì)消耗一定的內(nèi)存空間和時(shí)間。

rehash 操作不會(huì)直接影響哈希結(jié)果。哈希結(jié)果是由哈希函數(shù)計(jì)算得出的,與 Map 中元素的數(shù)量和布局無(wú)關(guān)。rehash 操作只會(huì)影響哈希表的布局,即每個(gè)鍵在哈希表中的位置會(huì)發(fā)生變化,但是每個(gè)鍵的哈希值并不會(huì)改變。

9. Map Rehash 過(guò)程中存放在舊桶的元素如何遷移

rehash 操作會(huì)創(chuàng)建一個(gè)新的哈希表,同時(shí)保留舊的哈希表不變。然后,它會(huì)依次遍歷舊哈希表中的每個(gè)桶,將桶中的所有鍵值對(duì)復(fù)制到新哈希表中對(duì)應(yīng)的桶中。在遍歷每個(gè)桶時(shí),如果桶中的元素已經(jīng)被刪除,則跳過(guò)這些元素。

當(dāng)遍歷到一個(gè)桶時(shí),Map 實(shí)現(xiàn)會(huì)首先獲取舊哈希表中該桶的互斥鎖,以確保在復(fù)制元素時(shí)不會(huì)有并發(fā)訪問(wèn)的問(wèn)題。然后,它會(huì)遍歷桶中的所有鍵值對(duì),對(duì)于每個(gè)鍵值對(duì),它會(huì)計(jì)算鍵在新哈希表中的位置,并將鍵值對(duì)插入到對(duì)應(yīng)的桶中。插入過(guò)程中,如果新哈希表中對(duì)應(yīng)的桶已經(jīng)存在元素,則會(huì)將新元素插入到該桶的鏈表的尾部。

在整個(gè) rehash 過(guò)程中,新哈希表會(huì)保持為空,直到所有元素都被復(fù)制完畢。復(fù)制完成后,Map 實(shí)現(xiàn)會(huì)用新哈希表替換舊哈希表,并釋放舊哈希表占用的內(nèi)存空間。這樣,Map 中的所有元素都被遷移到了新哈希表中。

需要注意的是,在 rehash 過(guò)程中,如果有并發(fā)訪問(wèn) Map,則可能會(huì)發(fā)生競(jìng)爭(zhēng)條件。因此,Go 語(yǔ)言中的 Map 不是線程安全的。如果需要在多個(gè) goroutine 中訪問(wèn) Map,則需要使用互斥鎖或其他并發(fā)安全的機(jī)制來(lái)保護(hù)訪問(wèn)

10. sync.Map 的 Load() 方法流程

func (m *Map) Load(key any) (value any, ok bool) {
   read, _ := m.read.Load().(readOnly)
   e, ok := read.m[key]
   if !ok && read.amended {
      m.mu.Lock()
      // Avoid reporting a spurious miss if m.dirty got promoted while we were
      // blocked on m.mu. (If further loads of the same key will not miss, it's
      // not worth copying the dirty map for this key.)
      read, _ = m.read.Load().(readOnly)
      e, ok = read.m[key]
      if !ok && read.amended {
         e, ok = m.dirty[key]
         // Regardless of whether the entry was present, record a miss: this key
         // will take the slow path until the dirty map is promoted to the read
         // map.
         m.missLocked()
      }
      m.mu.Unlock()
   }
   if !ok {
      return nil, false
   }
   return e.load()
}

可見(jiàn)Load函數(shù)直接從底層讀取元素,如果存在則返回,不管此時(shí)是否有寫(xiě)入操作。因?yàn)?code>e.load函數(shù)內(nèi)是通過(guò)原子操作讀取數(shù)據(jù)的。

因此當(dāng)key存在的時(shí)候,Load函數(shù)不會(huì)加鎖。Stone當(dāng)元素存在的時(shí)候也不會(huì)加鎖,而是通過(guò)atomic.CompareAndSwapPointer修改元素的值。

所以Load,Store只有當(dāng)key不存在的時(shí)候才會(huì)加鎖,其他情況不會(huì)加鎖,因此它適合讀多寫(xiě)少的場(chǎng)景,速度非常快。

到此這篇關(guān)于十個(gè)Go map面試常考問(wèn)題合集的文章就介紹到這了,更多相關(guān)Go map內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言中validation庫(kù)不能校驗(yàn)零值問(wèn)題的解決方法

    Go語(yǔ)言中validation庫(kù)不能校驗(yàn)零值問(wèn)題的解決方法

    在使用 Gin 框架的時(shí)候,前后端傳遞數(shù)據(jù)的時(shí)候,比如使用 JSON 格式,通常會(huì)使用 ShouldBindJSON 去用結(jié)構(gòu)體打 tag 綁定前端傳來(lái)的 JSON 格式數(shù)據(jù),本文給大家介紹了Go語(yǔ)言中validation庫(kù)不能校驗(yàn)零值問(wèn)題的解決方法,需要的朋友可以參考下
    2024-08-08
  • Go cobra庫(kù)使用教程

    Go cobra庫(kù)使用教程

    cobra既是一個(gè)用于創(chuàng)建強(qiáng)大現(xiàn)代CLI應(yīng)用程序的庫(kù),也是一個(gè)生成應(yīng)用程序和命令文件的程序。cobra被用在很多go語(yǔ)言的項(xiàng)目中,比如 Kubernetes、Docker、Istio、ETCD、Hugo、Github CLI等等
    2022-12-12
  • 詳解Go語(yǔ)言中Get/Post請(qǐng)求測(cè)試

    詳解Go語(yǔ)言中Get/Post請(qǐng)求測(cè)試

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中的環(huán)境安裝以及Get和Post請(qǐng)求接口的測(cè)試,文中的示例代碼講解詳細(xì),感興趣的可以跟隨小編一起學(xué)習(xí)一下
    2022-06-06
  • Golang channel死鎖的幾種情況小結(jié)

    Golang channel死鎖的幾種情況小結(jié)

    本文主要介紹了Golang channel死鎖的幾種情況小結(jié),詳細(xì)的介紹了六種情況,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • Go語(yǔ)言入門13之runtime包案例講解

    Go語(yǔ)言入門13之runtime包案例講解

    這篇文章主要介紹了Go語(yǔ)言入門runtime包相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05
  • Go語(yǔ)言omitempty選項(xiàng)的實(shí)現(xiàn)

    Go語(yǔ)言omitempty選項(xiàng)的實(shí)現(xiàn)

    本文主要介紹了Go語(yǔ)言omitempty選項(xiàng)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 重學(xué)Go語(yǔ)言之如何開(kāi)發(fā)RPC應(yīng)用

    重學(xué)Go語(yǔ)言之如何開(kāi)發(fā)RPC應(yīng)用

    這篇文章主要為大家詳細(xì)介紹了在Go語(yǔ)言中如何構(gòu)建RPC應(yīng)用,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09
  • golang Iris運(yùn)行多個(gè)應(yīng)用的實(shí)現(xiàn)

    golang Iris運(yùn)行多個(gè)應(yīng)用的實(shí)現(xiàn)

    本文主要介紹了golang Iris運(yùn)行多個(gè)應(yīng)用的實(shí)現(xiàn),在Iris里面,提供了一種方式可以讓我們同時(shí)運(yùn)行多個(gè)應(yīng)用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Apache?IoTDB開(kāi)發(fā)系統(tǒng)之Go原生接口方法

    Apache?IoTDB開(kāi)發(fā)系統(tǒng)之Go原生接口方法

    這篇文章主要為大家介紹了?Apache?IoTDB開(kāi)發(fā)系統(tǒng)之Go原生接口方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • Golang設(shè)計(jì)模式之外觀模式的實(shí)現(xiàn)

    Golang設(shè)計(jì)模式之外觀模式的實(shí)現(xiàn)

    這篇文章主要介紹了Golang設(shè)計(jì)模式之外觀模式的實(shí)現(xiàn),外觀模式是一種常用的設(shè)計(jì)模式之一,是一種結(jié)構(gòu)型設(shè)計(jì)模式,它提供了一個(gè)簡(jiǎn)單的接口來(lái)訪問(wèn)復(fù)雜系統(tǒng)的各種功能,從而降低了系統(tǒng)的復(fù)雜度,需要詳細(xì)了解可以參考下文
    2023-05-05

最新評(píng)論