本文目錄如下,閱讀本文后,將一網(wǎng)打盡下面Golang Map相關(guān)面試題
成都創(chuàng)新互聯(lián)公司主營(yíng)南皮網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,重慶APP軟件開發(fā),南皮h5成都小程序開發(fā)搭建,南皮網(wǎng)站營(yíng)銷推廣歡迎南皮等地區(qū)企業(yè)咨詢
Go中的map是一個(gè)指針,占用8個(gè)字節(jié),指向hmap結(jié)構(gòu)體; 源碼 src/runtime/map.go 中可以看到map的底層結(jié)構(gòu)
每個(gè)map的底層結(jié)構(gòu)是hmap,hmap包含若干個(gè)結(jié)構(gòu)為bmap的bucket數(shù)組。每個(gè)bucket底層都采用鏈表結(jié)構(gòu)。接下來,我們來詳細(xì)看下map的結(jié)構(gòu)
bmap 就是我們常說的“桶”,一個(gè)桶里面會(huì)最多裝 8 個(gè) key,這些 key 之所以會(huì)落入同一個(gè)桶,是因?yàn)樗鼈兘?jīng)過哈希計(jì)算后,哈希結(jié)果是“一類”的,關(guān)于key的定位我們?cè)趍ap的查詢和插入中詳細(xì)說明。在桶內(nèi),又會(huì)根據(jù) key 計(jì)算出來的 hash 值的高 8 位來決定 key 到底落入桶內(nèi)的哪個(gè)位置(一個(gè)桶內(nèi)最多有8個(gè)位置)。
bucket內(nèi)存數(shù)據(jù)結(jié)構(gòu)可視化如下:
注意到 key 和 value 是各自放在一起的,并不是 key/value/key/value/... 這樣的形式。源碼里說明這樣的好處是在某些情況下可以省略掉 padding字段,節(jié)省內(nèi)存空間。
當(dāng) map 的 key 和 value 都不是指針,并且 size 都小于 128 字節(jié)的情況下,會(huì)把 bmap 標(biāo)記為不含指針,這樣可以避免 gc 時(shí)掃描整個(gè) hmap。但是,我們看 bmap 其實(shí)有一個(gè) overflow 的字段,是指針類型的,破壞了 bmap 不含指針的設(shè)想,這時(shí)會(huì)把 overflow 移動(dòng)到 extra 字段來。
map是個(gè)指針,底層指向hmap,所以是個(gè)引用類型
golang 有三個(gè)常用的高級(jí)類型 slice 、map、channel, 它們都是 引用類型 ,當(dāng)引用類型作為函數(shù)參數(shù)時(shí),可能會(huì)修改原內(nèi)容數(shù)據(jù)。
golang 中沒有引用傳遞,只有值和指針傳遞。所以 map 作為函數(shù)實(shí)參傳遞時(shí)本質(zhì)上也是值傳遞,只不過因?yàn)?map 底層數(shù)據(jù)結(jié)構(gòu)是通過指針指向?qū)嶋H的元素存儲(chǔ)空間,在被調(diào)函數(shù)中修改 map,對(duì)調(diào)用者同樣可見,所以 map 作為函數(shù)實(shí)參傳遞時(shí)表現(xiàn)出了引用傳遞的效果。
因此,傳遞 map 時(shí),如果想修改map的內(nèi)容而不是map本身,函數(shù)形參無需使用指針
map 底層數(shù)據(jù)結(jié)構(gòu)是通過指針指向?qū)嶋H的元素 存儲(chǔ)空間 ,這種情況下,對(duì)其中一個(gè)map的更改,會(huì)影響到其他map
map 在沒有被修改的情況下,使用 range 多次遍歷 map 時(shí)輸出的 key 和 value 的順序可能不同。這是 Go 語言的設(shè)計(jì)者們有意為之,在每次 range 時(shí)的順序被隨機(jī)化,旨在提示開發(fā)者們,Go 底層實(shí)現(xiàn)并不保證 map 遍歷順序穩(wěn)定,請(qǐng)大家不要依賴 range 遍歷結(jié)果順序。
map 本身是無序的,且遍歷時(shí)順序還會(huì)被隨機(jī)化,如果想順序遍歷 map,需要對(duì) map key 先排序,再按照 key 的順序遍歷 map。
map默認(rèn)是并發(fā)不安全的,原因如下:
Go 官方在經(jīng)過了長(zhǎng)時(shí)間的討論后,認(rèn)為 Go map 更應(yīng)適配典型使用場(chǎng)景(不需要從多個(gè) goroutine 中進(jìn)行安全訪問),而不是為了小部分情況(并發(fā)訪問),導(dǎo)致大部分程序付出加鎖代價(jià)(性能),決定了不支持。
場(chǎng)景: 2個(gè)協(xié)程同時(shí)讀和寫,以下程序會(huì)出現(xiàn)致命錯(cuò)誤:fatal error: concurrent map writes
如果想實(shí)現(xiàn)map線程安全,有兩種方式:
方式一:使用讀寫鎖 map + sync.RWMutex
方式二:使用golang提供的 sync.Map
sync.map是用讀寫分離實(shí)現(xiàn)的,其思想是空間換時(shí)間。和map+RWLock的實(shí)現(xiàn)方式相比,它做了一些優(yōu)化:可以無鎖訪問read map,而且會(huì)優(yōu)先操作read map,倘若只操作read map就可以滿足要求(增刪改查遍歷),那就不用去操作write map(它的讀寫都要加鎖),所以在某些特定場(chǎng)景中它發(fā)生鎖競(jìng)爭(zhēng)的頻率會(huì)遠(yuǎn)遠(yuǎn)小于map+RWLock的實(shí)現(xiàn)方式。
golang中map是一個(gè)kv對(duì)集合。底層使用hash table,用鏈表來解決沖突 ,出現(xiàn)沖突時(shí),不是每一個(gè)key都申請(qǐng)一個(gè)結(jié)構(gòu)通過鏈表串起來,而是以bmap為最小粒度掛載,一個(gè)bmap可以放8個(gè)kv。在哈希函數(shù)的選擇上,會(huì)在程序啟動(dòng)時(shí),檢測(cè) cpu 是否支持 aes,如果支持,則使用 aes hash,否則使用 memhash。
map有3鐘初始化方式,一般通過make方式創(chuàng)建
map的創(chuàng)建通過生成匯編碼可以知道,make創(chuàng)建map時(shí)調(diào)用的底層函數(shù)是 runtime.makemap 。如果你的map初始容量小于等于8會(huì)發(fā)現(xiàn)走的是 runtime.fastrand 是因?yàn)槿萘啃∮?時(shí)不需要生成多個(gè)桶,一個(gè)桶的容量就可以滿足
makemap函數(shù)會(huì)通過 fastrand 創(chuàng)建一個(gè)隨機(jī)的哈希種子,然后根據(jù)傳入的 hint 計(jì)算出需要的最小需要的桶的數(shù)量,最后再使用 makeBucketArray 創(chuàng)建用于保存桶的數(shù)組,這個(gè)方法其實(shí)就是根據(jù)傳入的 B 計(jì)算出的需要?jiǎng)?chuàng)建的桶數(shù)量在內(nèi)存中分配一片連續(xù)的空間用于存儲(chǔ)數(shù)據(jù),在創(chuàng)建桶的過程中還會(huì)額外創(chuàng)建一些用于保存溢出數(shù)據(jù)的桶,數(shù)量是 2^(B-4) 個(gè)。初始化完成返回hmap指針。
找到一個(gè) B,使得 map 的裝載因子在正常范圍內(nèi)
Go 語言中讀取 map 有兩種語法:帶 comma 和 不帶 comma。當(dāng)要查詢的 key 不在 map 里,帶 comma 的用法會(huì)返回一個(gè) bool 型變量提示 key 是否在 map 中;而不帶 comma 的語句則會(huì)返回一個(gè) value 類型的零值。如果 value 是 int 型就會(huì)返回 0,如果 value 是 string 類型,就會(huì)返回空字符串。
map的查找通過生成匯編碼可以知道,根據(jù) key 的不同類型,編譯器會(huì)將查找函數(shù)用更具體的函數(shù)替換,以優(yōu)化效率:
函數(shù)首先會(huì)檢查 map 的標(biāo)志位 flags。如果 flags 的寫標(biāo)志位此時(shí)被置 1 了,說明有其他協(xié)程在執(zhí)行“寫”操作,進(jìn)而導(dǎo)致程序 panic。這也說明了 map 對(duì)協(xié)程是不安全的。
key經(jīng)過哈希函數(shù)計(jì)算后,得到的哈希值如下(主流64位機(jī)下共 64 個(gè) bit 位):
m: 桶的個(gè)數(shù)
從buckets 通過 hash m 得到對(duì)應(yīng)的bucket,如果bucket正在擴(kuò)容,并且沒有擴(kuò)容完成,則從oldbuckets得到對(duì)應(yīng)的bucket
計(jì)算hash所在桶編號(hào):
用上一步哈希值最后的 5 個(gè) bit 位,也就是 01010 ,值為 10,也就是 10 號(hào)桶(范圍是0~31號(hào)桶)
計(jì)算hash所在的槽位:
用上一步哈希值哈希值的高8個(gè)bit 位,也就是 10010111 ,轉(zhuǎn)化為十進(jìn)制,也就是151,在 10 號(hào) bucket 中尋找** tophash 值(HOB hash)為 151* 的 槽位**,即為key所在位置,找到了 2 號(hào)槽位,這樣整個(gè)查找過程就結(jié)束了。
如果在 bucket 中沒找到,并且 overflow 不為空,還要繼續(xù)去 overflow bucket 中尋找,直到找到或是所有的 key 槽位都找遍了,包括所有的 overflow bucket。
通過上面找到了對(duì)應(yīng)的槽位,這里我們?cè)僭敿?xì)分析下key/value值是如何獲取的:
bucket 里 key 的起始地址就是 unsafe.Pointer(b)+dataOffset。第 i 個(gè) key 的地址就要在此基礎(chǔ)上跨過 i 個(gè) key 的大??;而我們又知道,value 的地址是在所有 key 之后,因此第 i 個(gè) value 的地址還需要加上所有 key 的偏移。
通過匯編語言可以看到,向 map 中插入或者修改 key,最終調(diào)用的是 mapassign 函數(shù)。
實(shí)際上插入或修改 key 的語法是一樣的,只不過前者操作的 key 在 map 中不存在,而后者操作的 key 存在 map 中。
mapassign 有一個(gè)系列的函數(shù),根據(jù) key 類型的不同,編譯器會(huì)將其優(yōu)化為相應(yīng)的“快速函數(shù)”。
我們只用研究最一般的賦值函數(shù) mapassign 。
map的賦值會(huì)附帶著map的擴(kuò)容和遷移,map的擴(kuò)容只是將底層數(shù)組擴(kuò)大了一倍,并沒有進(jìn)行數(shù)據(jù)的轉(zhuǎn)移,數(shù)據(jù)的轉(zhuǎn)移是在擴(kuò)容后逐步進(jìn)行的,在遷移的過程中每進(jìn)行一次賦值(access或者delete)會(huì)至少做一次遷移工作。
1.判斷map是否為nil
每一次進(jìn)行賦值/刪除操作時(shí),只要oldbuckets != nil 則認(rèn)為正在擴(kuò)容,會(huì)做一次遷移工作,下面會(huì)詳細(xì)說下遷移過程
根據(jù)上面查找過程,查找key所在位置,如果找到則更新,沒找到則找空位插入即可
經(jīng)過前面迭代尋找動(dòng)作,若沒有找到可插入的位置,意味著需要擴(kuò)容進(jìn)行插入,下面會(huì)詳細(xì)說下擴(kuò)容過程
通過匯編語言可以看到,向 map 中刪除 key,最終調(diào)用的是 mapdelete 函數(shù)
刪除的邏輯相對(duì)比較簡(jiǎn)單,大多函數(shù)在賦值操作中已經(jīng)用到過,核心還是找到 key 的具體位置。尋找過程都是類似的,在 bucket 中挨個(gè) cell 尋找。找到對(duì)應(yīng)位置后,對(duì) key 或者 value 進(jìn)行“清零”操作,將 count 值減 1,將對(duì)應(yīng)位置的 tophash 值置成 Empty
再來說觸發(fā) map 擴(kuò)容的時(shí)機(jī):在向 map 插入新 key 的時(shí)候,會(huì)進(jìn)行條件檢測(cè),符合下面這 2 個(gè)條件,就會(huì)觸發(fā)擴(kuò)容:
1、裝載因子超過閾值
源碼里定義的閾值是 6.5 (loadFactorNum/loadFactorDen),是經(jīng)過測(cè)試后取出的一個(gè)比較合理的因子
我們知道,每個(gè) bucket 有 8 個(gè)空位,在沒有溢出,且所有的桶都裝滿了的情況下,裝載因子算出來的結(jié)果是 8。因此當(dāng)裝載因子超過 6.5 時(shí),表明很多 bucket 都快要裝滿了,查找效率和插入效率都變低了。在這個(gè)時(shí)候進(jìn)行擴(kuò)容是有必要的。
對(duì)于條件 1,元素太多,而 bucket 數(shù)量太少,很簡(jiǎn)單:將 B 加 1,bucket 最大數(shù)量( 2^B )直接變成原來 bucket 數(shù)量的 2 倍。于是,就有新老 bucket 了。注意,這時(shí)候元素都在老 bucket 里,還沒遷移到新的 bucket 來。新 bucket 只是最大數(shù)量變?yōu)樵瓉碜畲髷?shù)量的 2 倍( 2^B * 2 ) 。
2、overflow 的 bucket 數(shù)量過多
在裝載因子比較小的情況下,這時(shí)候 map 的查找和插入效率也很低,而第 1 點(diǎn)識(shí)別不出來這種情況。表面現(xiàn)象就是計(jì)算裝載因子的分子比較小,即 map 里元素總數(shù)少,但是 bucket 數(shù)量多(真實(shí)分配的 bucket 數(shù)量多,包括大量的 overflow bucket)
不難想像造成這種情況的原因:不停地插入、刪除元素。先插入很多元素,導(dǎo)致創(chuàng)建了很多 bucket,但是裝載因子達(dá)不到第 1 點(diǎn)的臨界值,未觸發(fā)擴(kuò)容來緩解這種情況。之后,刪除元素降低元素總數(shù)量,再插入很多元素,導(dǎo)致創(chuàng)建很多的 overflow bucket,但就是不會(huì)觸發(fā)第 1 點(diǎn)的規(guī)定,你能拿我怎么辦?overflow bucket 數(shù)量太多,導(dǎo)致 key 會(huì)很分散,查找插入效率低得嚇人,因此出臺(tái)第 2 點(diǎn)規(guī)定。這就像是一座空城,房子很多,但是住戶很少,都分散了,找起人來很困難
對(duì)于條件 2,其實(shí)元素沒那么多,但是 overflow bucket 數(shù)特別多,說明很多 bucket 都沒裝滿。解決辦法就是開辟一個(gè)新 bucket 空間,將老 bucket 中的元素移動(dòng)到新 bucket,使得同一個(gè) bucket 中的 key 排列地更緊密。這樣,原來,在 overflow bucket 中的 key 可以移動(dòng)到 bucket 中來。結(jié)果是節(jié)省空間,提高 bucket 利用率,map 的查找和插入效率自然就會(huì)提升。
由于 map 擴(kuò)容需要將原有的 key/value 重新搬遷到新的內(nèi)存地址,如果有大量的 key/value 需要搬遷,會(huì)非常影響性能。因此 Go map 的擴(kuò)容采取了一種稱為“漸進(jìn)式”的方式,原有的 key 并不會(huì)一次性搬遷完畢,每次最多只會(huì)搬遷 2 個(gè) bucket。
上面說的 hashGrow() 函數(shù)實(shí)際上并沒有真正地“搬遷”,它只是分配好了新的 buckets,并將老的 buckets 掛到了 oldbuckets 字段上。真正搬遷 buckets 的動(dòng)作在 growWork() 函數(shù)中,而調(diào)用 growWork() 函數(shù)的動(dòng)作是在 mapassign 和 mapdelete 函數(shù)中。也就是插入或修改、刪除 key 的時(shí)候,都會(huì)嘗試進(jìn)行搬遷 buckets 的工作。先檢查 oldbuckets 是否搬遷完畢,具體來說就是檢查 oldbuckets 是否為 nil。
如果未遷移完畢,賦值/刪除的時(shí)候,擴(kuò)容完畢后(預(yù)分配內(nèi)存),不會(huì)馬上就進(jìn)行遷移。而是采取 增量擴(kuò)容 的方式,當(dāng)有訪問到具體 bukcet 時(shí),才會(huì)逐漸的進(jìn)行遷移(將 oldbucket 遷移到 bucket)
nevacuate 標(biāo)識(shí)的是當(dāng)前的進(jìn)度,如果都搬遷完,應(yīng)該和2^B的長(zhǎng)度是一樣的
在evacuate 方法實(shí)現(xiàn)是把這個(gè)位置對(duì)應(yīng)的bucket,以及其沖突鏈上的數(shù)據(jù)都轉(zhuǎn)移到新的buckets上。
轉(zhuǎn)移的判斷直接通過tophash 就可以,判斷tophash中第一個(gè)hash值即可
遍歷的過程,就是按順序遍歷 bucket,同時(shí)按順序遍歷 bucket 中的 key。
map遍歷是無序的,如果想實(shí)現(xiàn)有序遍歷,可以先對(duì)key進(jìn)行排序
為什么遍歷 map 是無序的?
如果發(fā)生過遷移,key 的位置發(fā)生了重大的變化,有些 key 飛上高枝,有些 key 則原地不動(dòng)。這樣,遍歷 map 的結(jié)果就不可能按原來的順序了。
如果就一個(gè)寫死的 map,不會(huì)向 map 進(jìn)行插入刪除的操作,按理說每次遍歷這樣的 map 都會(huì)返回一個(gè)固定順序的 key/value 序列吧。但是 Go 杜絕了這種做法,因?yàn)檫@樣會(huì)給新手程序員帶來誤解,以為這是一定會(huì)發(fā)生的事情,在某些情況下,可能會(huì)釀成大錯(cuò)。
Go 做得更絕,當(dāng)我們?cè)诒闅v map 時(shí),并不是固定地從 0 號(hào) bucket 開始遍歷,每次都是從一個(gè)**隨機(jī)值序號(hào)的 bucket 開始遍歷,并且是從這個(gè) bucket 的一個(gè) 隨機(jī)序號(hào)的 cell **開始遍歷。這樣,即使你是一個(gè)寫死的 map,僅僅只是遍歷它,也不太可能會(huì)返回一個(gè)固定序列的 key/value 對(duì)了。
于此之外還有讀寫鎖,即
給?個(gè) nil channel 發(fā)送數(shù)據(jù),造成永遠(yuǎn)阻塞
從?個(gè) nil channel 接收數(shù)據(jù),造成永遠(yuǎn)阻塞
給?個(gè)已經(jīng)關(guān)閉的 channel 發(fā)送數(shù)據(jù),引起 panic
從?個(gè)已經(jīng)關(guān)閉的 channel 接收數(shù)據(jù),如果緩沖區(qū)中為空,則返回?個(gè)零值
?緩沖的channel是同步的,?有緩沖的channel是?同步的
請(qǐng)實(shí)現(xiàn) 個(gè)算法,確定 個(gè)字符串的所有字符【是否全都不同】。這 我們要求【不允
許使 額外的存儲(chǔ)結(jié)構(gòu)】。 給定 個(gè)string,請(qǐng)返回 個(gè)bool值,true代表所有字符全都
不同,false代表存在相同的字符。 保證字符串中的字符為【ASCII字符】。字符串的
度 于等于【3000】。
這 有 個(gè)重點(diǎn),第 個(gè)是 ASCII字符 , ASCII字符 字符 共有256個(gè),其中128個(gè)是常
字符,可以在鍵盤上輸 。128之后的是鍵盤上 法找到的。
然后是全部不同,也就是字符串中的字符沒有重復(fù)的,再次,不準(zhǔn)使 額外的儲(chǔ)存結(jié)
構(gòu),且字符串 于等于3000。
如果允許其他額外儲(chǔ)存結(jié)構(gòu),這個(gè)題 很好做。如果不允許的話,可以使 golang內(nèi)置
的 式實(shí)現(xiàn)。
通過 strings.Count 函數(shù)判斷:
使 的是golang內(nèi)置 法 strings.Count ,可以 來判斷在 個(gè)字符串中包含
的另外 個(gè)字符串的數(shù)量
還有不同的方法同樣可以實(shí)現(xiàn),你了解嗎?
推薦go相關(guān)技術(shù) 專欄
gRPC-go源碼剖析與實(shí)戰(zhàn)_帶你走進(jìn)gRPC-go的源碼世界-CSDN博客
Hello,大家好,又見面了!上一遍我們將 channel 相關(guān)基礎(chǔ)以及使用場(chǎng)景。這一篇,還需要再次進(jìn)階理解channel 阻塞問題。以下創(chuàng)建一個(gè)chan類型為int,cap 為3。
channel 內(nèi)部其實(shí)是一個(gè)環(huán)形buf數(shù)據(jù)結(jié)構(gòu) ,是一種滑動(dòng)窗口機(jī)制,當(dāng)make完后,就分配在 Heap 上。
上面,向 chan 發(fā)送一條“hello”數(shù)據(jù):
如果 G1 發(fā)送數(shù)據(jù)超過指定cap時(shí),會(huì)出現(xiàn)什么情況?
看下面實(shí)例:
以上會(huì)出現(xiàn)什么,chan 緩沖區(qū)允許大小為1,如果再往chan仍數(shù)據(jù),滿了就會(huì)被阻塞,那么是如何實(shí)現(xiàn)阻塞的呢?當(dāng) chan 滿時(shí),會(huì)進(jìn)入 gopark,此時(shí) G1 進(jìn)入一個(gè) waiting 狀態(tài),然后會(huì)創(chuàng)建一個(gè) sudog 對(duì)象,其實(shí)就sendq隊(duì)列,把 200放進(jìn)去。等 buf 不滿的時(shí)候,再喚醒放入buf里面。
通過如下源碼,你會(huì)更加清晰:
上面,從 chan 獲取數(shù)據(jù):
Go 語言核心思想:“Do not communicate by sharing memory; instead, share memory by communicating.” 你可以看看這本書名叫:Effective Go
如果接收者,接收一個(gè)空對(duì)象,也會(huì)發(fā)生什么情況?
代碼示例 :
也會(huì)報(bào)錯(cuò)如下:
上面,從 chan 取出數(shù)據(jù),可是沒有數(shù)據(jù)了。此時(shí),它會(huì)把 接收者 G2 阻塞掉,也是和G1發(fā)送者一樣,也會(huì)執(zhí)行 gopark 將狀態(tài)改為 waiting,不一樣的點(diǎn)就是。
正常情況下,接收者G2作為取出數(shù)據(jù)是去 buf 讀取數(shù)據(jù)的,但現(xiàn)在,buf 為空了,此時(shí),接收者G2會(huì)將sudog導(dǎo)出來,因?yàn)楝F(xiàn)在G2已經(jīng)被阻塞了嘛,會(huì)把G2給G,然后將 t := -ch 中變量 t 是在棧上的地址,放進(jìn)去 elem ,也就是說,只存它的地址指針在sudog里面。
最后, ch - 200 當(dāng)G1往 chan 添加200這個(gè)數(shù)據(jù),正常情況是將數(shù)據(jù)添加到buf里面,然后喚醒 G2 是吧,而現(xiàn)在是將 G1 的添加200數(shù)據(jù)直接干到剛才G2阻塞的t這里變量里面。
你會(huì)認(rèn)為,這樣真的可以嗎?想一想,G2 本來就是已經(jīng)阻塞了,然后我們直接這么干肯定沒有什么毛病,而且效率提高了,不需要再次放入buf再取出,這個(gè)過程也是需要時(shí)間。不然,不得往chan添加數(shù)據(jù)需要加鎖、拷貝、解鎖一序列操作,那肯定就慢了,我想Go語言是為了高效及內(nèi)存使用率的考慮這樣設(shè)計(jì)的。(注意,一般都是在runtime里面完成,不然會(huì)出現(xiàn)象安全問題。)
總結(jié) :
chan 類型的特點(diǎn):chan 如果為空,receiver 接收數(shù)據(jù)的時(shí)候就會(huì)阻塞等待,直到 chan 被關(guān)閉或者有新的數(shù)據(jù)到來。有這種個(gè)機(jī)制,就可以實(shí)現(xiàn) wait/notify 的設(shè)計(jì)模式。
相關(guān)面試題:
使用go語言的好處: go語言的設(shè)計(jì)是務(wù)實(shí)的, go在針對(duì)并發(fā)上進(jìn)行了優(yōu)化, 并且支持大規(guī)模高并發(fā), 又由于單一的碼格式, 相比于其他語言更具有可讀性, 在垃圾回收上比java和Python更有效, 因?yàn)樗呛统绦蛲瑫r(shí)執(zhí)行的.
1. 進(jìn)程, 線程, 協(xié)程的區(qū)別, 協(xié)程的優(yōu)勢(shì)
2. 講一下GMP模型(重點(diǎn))
3. Go的GC, 混合寫屏障(重點(diǎn))
4. go的Slice和數(shù)組的區(qū)別, slice的擴(kuò)容原理(重點(diǎn))
5. 講一下channel,實(shí)現(xiàn)原理(重點(diǎn))
6. 講一下Go的Map的實(shí)現(xiàn)原理, 是否線程安全, 如何實(shí)現(xiàn)安全(重點(diǎn))
7. new 和 make 的區(qū)別
8. 說一下內(nèi)存逃逸
9. 函數(shù)傳指針和傳值有什么區(qū)別
10. goroutine之間的通信方式
11. 測(cè)試是怎么做的(單元測(cè)試, 壓力測(cè)試)
12. 堆和棧的區(qū)別
請(qǐng)實(shí)現(xiàn) 個(gè)算法,在不使 【額外數(shù)據(jù)結(jié)構(gòu)和儲(chǔ)存空間】的情況下,翻轉(zhuǎn) 個(gè)給定的字
符串(可以使 單個(gè)過程變量)。
給定 個(gè)string,請(qǐng)返回 個(gè)string,為翻轉(zhuǎn)后的字符串。保證字符串的 度 于等于
5000。
翻轉(zhuǎn)字符串其實(shí)是將 個(gè)字符串以中間字符為軸,前后翻轉(zhuǎn),即將str[len]賦值給str[0],
將str[0] 賦值 str[len]。
網(wǎng)站欄目:整理go語言面試題,go算法面試題
URL網(wǎng)址:http://jinyejixie.com/article42/hsidhc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、網(wǎng)站設(shè)計(jì)公司、網(wǎng)站維護(hù)、App開發(fā)、外貿(mào)建站、云服務(wù)器
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)