天天看點

Go語言最新面試題及其解析(一)

原文連結

1.select是随機的還是順序的?

select會随機選擇一個可用通道做收發操作

2.Go語言局部變量配置設定在棧還是堆?

Go語言編譯器會自動決定把一個變量放在棧還是放在堆,編譯器會做逃逸分析,當發現變量的作用域沒有跑出函數範圍,就可以在棧上,反之則必須配置設定在堆。

檢視資料

3.簡述一下你對Go垃圾回收機制的了解?

v1.1 STW

v1.3 Mark STW, Sweep 并行

v1.5 三色标記法

v1.8 hybrid write barrier(混合寫屏障:優化STW)

Golang垃圾回收剖析

4.簡述一下golang的協程排程原理?

M(machine): 代表着真正的執行計算資源,可以認為它就是os thread(系統線程)。

P(processor): 表示邏輯processor,是線程M的執行的上下文。

G(goroutine): 排程系統的最基本機關goroutine,存儲了goroutine的執行stack資訊、goroutine狀态以及goroutine的任務函數等。

5.介紹下 golang 的 runtime 機制?

Runtime 負責管理任務排程,垃圾收集及運作環境。同時,Go提供了一些進階的功能,如goroutine, channel, 以及Garbage collection。這些進階功能需要一個runtime的支援. runtime和使用者編譯後的代碼被linker靜态連結起來,形成一個可執行檔案。這個檔案從作業系統角度來說是一個user space的獨立的可執行檔案。 從運作的角度來說,這個檔案由2部分組成,一部分是使用者的代碼,另一部分就是runtime。runtime通過接口函數調用來管理goroutine, channel及其他一些進階的功能。從使用者代碼發起的調用作業系統API的調用都會被runtime攔截并處理。

Go runtime的一個重要的組成部分是goroutine scheduler。他負責追蹤,排程每個goroutine運作,實際上是從應用程式的process所屬的thread pool中配置設定一個thread來執行這個goroutine。是以,和java虛拟機中的Java thread和OS thread映射概念類似,每個goroutine隻有配置設定到一個OS thread才能運作。

相關資料

6.如何擷取 go 程式運作時的協程數量, gc 時間, 對象數, 堆棧資訊?

調用接口 runtime.ReadMemStats 可以擷取以上所有資訊, 注意: 調用此接口會觸發 STW(Stop The World)

參考:

https://golang.org/pkg/runtime/#ReadMemStats

如果需要打入到日志系統, 可以使用 go 封裝好的包, 輸出 json 格式.

1、

https://golang.org/pkg/expvar/

2、

http://blog.studygolang.com/2017/06/expvar-in-action/

更深入的用法就是将得到的運作時資料導入到 ES 内部, 然後使用 Kibana 做 golang 的運作時監控, 可以實時擷取到運作的資訊(堆棧, 對象數, gc 時間, goroutine, 總記憶體使用等等),

具體資訊可以看 ReadMemStats 的那個結構體

效果大緻如下:

Go語言最新面試題及其解析(一)

7.介紹下你平時都是怎麼調試 golang 的 bug 以及性能問題的?

panic 調用棧

pprof

火焰圖(配合壓測)

使用go run -race 或者 go build -race 來進行競争檢測

檢視系統 磁盤IO/網絡IO/記憶體占用/CPU 占用(配合壓測)

8.簡單介紹下 golang 中 make 和 new 的差別

new(T) 是為一個 T 類型的新值配置設定空間, 并将此空間初始化為 T 的零值, 并傳回這塊記憶體空間的位址, 也就是 T 類型的指針 T, 該指針指向 T 類型值占用的那塊記憶體. make(T) 傳回的是初始化之後的 T, 且隻能用于 slice, map, channel 三種類型. make(T, args) 傳回初始化之後 T 類型的值, 且此新值并不是 T 類型的零值, 也不是 T 類型的指針 T, 而是 T 類型值經過初始化之後的引用.

參考:

https://www.cnblogs.com/ghj1976/archive/2013/02/12/2910384.html https://studygolang.com/articles/3496