GoLang Interview Questions

  sonic0002        2024-05-25 03:08:18       901        0          English  简体中文  繁体中文  ภาษาไทย  Tiếng Việt 

以下列出一些常見的 GoLang 面試問題以及根據作者經驗提供的相應答案。 此列表會經常更新,加入新的理解。 請繼續關注。

什麼是 GoLang 的 GMP 模型?

GoLang 使用 goroutine 來實現並發,並且以高並發支持而聞名,因為該語言定義了自己的 goroutine 調度和處理系統,該系統被稱為 GMP 模型。

它的工作原理是 M 通常被定義為正在產生的 OS 線程(然後每個 M 線程應與一個 Process 隊列相關聯,並且每個 Process 隊列可以有多個 goroutine。Process 隊列的數量由 GOMAXPROCS() 定義。當 M 處理完其關聯的 P 中的所有 G 時,它會從其他 M 竊取 G,也會從全域 P 隊列中竊取。

如果 M 由於 IO 阻塞或網路阻塞而掛起,它會將自己從 P 中分離出來,並且此 P 將與另一個可用的 M 相關聯,如果不存在,則會建立一個新的 M。

如果 goroutine 無法放入本地 P,它將被放入全域 P 隊列。 如果 M 無法從其他 M 竊取 G,它將從全域 P 隊列中獲取。

每個 goroutine 只有 2K 的堆疊大小,這非常小,這就是 GoLang 支持更多並發的原因。 並且這種 goroutine 執行之間的切換是基於使用者線程空間,因此切換上下文的成本與線程或進程相比不高

GoLang 中的 GC 機制是什麼?

有三個階段:Mark Setup、Mark 和 Mark Termination。 Mark Setup 和 Mark Terminations 是 STW。 Mark 階段是並發的。

在執行 Mark Setup 時,將開啟 Write Barrier 以確保資料完整性,然後它將等待所有正在運行的 goroutine 停止。 

當 Marking 開始時,它將佔用 25% 的 CPU,並為自己分配一個 P 來進行收集。 標記階段將標記仍在使用的 head,它會嘗試查看所有 goroutine 的堆疊並遍歷其 root 指標,然後從 root 遍歷並進行標記。 如果標記無法及時完成,它將執行 Mark Assist,這意味著要求其他應用程式 goroutine 幫助。 加快標記速度。

在執行 Mark Termination 時,Write Barrier 將被關閉,並且將完成清理工作。

何時開始執行 GC?

  • GC 百分比,即與先前 GC 週期中使用的記憶體相比,要分配的新記憶體的百分比。
  • 通過調用 runtime.GC() 手動觸發

Slice 的底層工作原理是什麼?

Slice 描述的是陣列的一部分,它與陣列不同。

Slice header 具有長度、容量以及第零個元素指標。 底層由陣列支持。 如果達到容量,則無法再增長,需要重新建立底層陣列並重新分配。 如果未達到容量,則可以在需要時增長。

Panic、defer 和 recover

對於 defer,它的工作方式是 FILO

  1. defer 語句被評估時,會評估 deferred 函數的參數。

  2. 在周圍函數返回後,以 Last In First Out 順序執行 Deferred 函數調用

  3. Deferred 函數可以讀取和分配給返回函數的命名返回值。

Panic 將返回執行,並且函數中的 defers 將繼續執行。 

Recover 僅在 deferred 函數內部有用。 在普通函數中,recover 沒有任何效果,也不會執行任何操作。

Defer recover 僅適用於當前 goroutine,它不適用於其產生的 goroutine。

Context,它非常強大

Context 介面中的 4 個函數: 

  • Deadline(),
  • Done(),
  • Err(),
  • Value(key interface{})

這樣做的好處是資源共享、goroutine 控制

有一些派生的 goroutine,例如 WithCancel、WithDeadline、WithTimeout、WithValue

WithCancel: 

  1. Cancel 函數將級聯到子上下文

  2. 建立新的子上下文時,它將在父上下文中註冊。 

WithValue

  1. 該鍵必須是可比較的,因為在調用 Value() 函數時存在 c.key == key 檢查

  2. slice、map 和函數不可比較。 主要是因為 slice 不可比較,因為它是一種引用類型,其中僅比較地址沒有意義,並且由於 len/cap 功能,比較 slice 中的內容的複雜性也會增加

Channel

Channel 是一種通過通信共享記憶體的方式

有緩衝和非緩衝通道

  • 關閉 nil 或已關閉的通道將會 panic
  • 將值發送到 nil 通道會永遠阻塞,關閉的通道將會 panic
  • 從 nil 通道接收資料會永遠阻塞,關閉的通道將立即返回

何時會發生 goroutine 洩漏?

一些情況包括:

  1. 當通道未關閉,而 goroutine 一直在等待從通道接收資料時
  2. 當某些資源未正確關閉,而某些 goroutine 仍在等待來自另一端的響應,並且沒有為阻塞 IO 設置足夠的超時時

new() 和 make() 之間有什麼區別?

new() 僅分配記憶體,而 make() 將初始化資料

使用 new() 建立的物件已準備好使用,但需要在需要時顯式初始化其屬性才能使用

make() 只能用於 slice、map 和 channel 類型。

詳細差異可以在這裡找到。

指標和非指標方法接收器之間的區別?

就像函數調用中的按引用傳遞按值傳遞一樣。

如果要改變 struct,或者 struct 對於接收器來說太大,則會選擇定義指標方法接收器。

如果某些函數具有指標接收器,則其餘函數也應該具有指標接收器,以保持一致性。

如何檢查 struct 是否實現了介面?

在 GoLang 中沒有像 Java 等其他語言那樣的 implements 關鍵字。 如果 struct 實現了介面的所有方法,則認為它實現了該介面。 如果 struct 代碼與介面定義不在同一位置,則可能難以找出 struct 是否實現了特定的介面。 在某些情況下,這可能會導致運行時問題。

有幾種方法可以檢查:

  • 使用虛擬物件進行類型斷言。 var _ = (SomeStruct{}).(SomeInterface)
  • 使用反射。 reflect.TypeOf(OneInterface).Implements(reflect.TypeOf(SomeInterface).Elem())

對於其他方法,可以在這裡找到。

MEMORY  CONCURRENCY  INTERVIEW QUESTION  GOLANG 

           

  RELATED


  0 COMMENT


No comment for this article.



  RANDOM FUN

I see TGIF, but where is Google?