golang初級面試:
new和make之間的區別?
例子:
var temp []int
// 相當於給 temp 變量分配了結構類型,沒有分配底層數組
// 所以 data = nil、存儲個數為0,容量也是0
var temp []int = make([]int, 4, 8)
temp = append(temp, 111, 222)
// 相當於為 temp 變量分配結構類型, 存儲個數為 4, 容量也是 8, 和分配底層數組
// 分配一塊容納 8 個元素的內存,還會初始化為默認 0
// 通過 append 進行賦值
temp := new([]int)
// 相當於給 temp 分配結構類型,但它不負責底層數組的分配,所以 data = nil、存儲、容量都是 0
// new的返回值就是該類型的起始內存地址,是沒有底層數組
// 需要通過 append 添加元素,才會開辟底層數組
func main() {
var temp []int
fmt.Println(temp)
var a []int = make([]int, 2, 4)
a = append(a, 11, 22)
fmt.Println(a)
b := new([]int)
fmt.Println(b)
*b = append(*b, 33333)
fmt.Println(b)
}
// slice 擴容規則
第一步:
ccc := []int{1, 2}
ccc = append(ccc, 333, 444, 555)
預估容量規則:
如果"老的容量" * 2 < 需要存儲的容量 ---> 新的容量 = 等於預估容量
否則再細分:
老元素個數 < 1024 ---> 預估容量直接翻倍
老元素個數 >= 1024 ---> 預估容量先擴容 1.25 倍
ccc 是 2 * 2 < 5 個元素,那預估容量就是 5 個元素
第二步 - 內存規格管理:
內存管理規格以 2 的倍數模式增長, 2、4、8、16、32、48、64
第三步:
32位操作系統為 4 個字節
64位操作系統為 8 個字節
5 個元素 * 8 個字節 = 40 Byte,最接近的是 48 Byte
實際用戶得到的是一個 48 字節的內存擴容空間,最多能裝 6 個元素,看元素占用的內存大小
new 只分配內存
make用於slice,map,和channel的初始化
new → 內置函數new按指定類型長度分配零值內存,返回指針,並不關心類型內部構造和初始化方式。
make → 內置函數make對引用類型進行創建,編譯器會將make轉換為目標類型專用的創建函數,以確保完成全部內存分配和相關屬性初始化。
Golang內存管理 - GC 標記回收?
GC 三色標記
調一個函數需要傳一個結構體,傳指針還是傳值?
看函數怎么定義,如果需要修改傳遞的參數,可以通過指針傳參,如果單一使用結構體參數,不做修改操作,可以用傳值方式
例子:
type B struct {
Name string
}
func (b B) Test1() {
fmt.Printf("Test1 addr:%p\n", &b)
fmt.Printf("Test1 name:%s\n", b.Name)
b.Name = "john"
}
func (b *B) Test2() {
fmt.Printf("Test2 addr:%p\n", b)
fmt.Printf("Test2 name:%s\n", b.Name)
b.Name = "john"
}
func main() {
b := B{}
b.Test1()
b.Test1()
b.Test2()
b.Test2()
}
/*
Test1 addr:0xc00003a250
Test1 name:
Test1 addr:0xc00003a260
Test1 name:
Test2 addr:0xc00003a240
Test2 name:
Test2 addr:0xc00003a240
Test2 name:john
*/
Linux中有幾種線程模型?Goroutine 的實現原理了解過嗎?
線程的實現曾有3種模型:
多對一(M:1)的用戶級線程模型
一對一(1:1)的內核級線程模型
多對多(M:N)的兩級線程模型
Goroutine 的實現原理:
S(Sched):結構就是調度器,它維護有存儲M和G的隊列以及調度器的一些狀態信息等。
M(Machine):一個M直接關聯了一個內核線程。
P(processor):代表了M所需的上下文環境,也是處理用戶級代碼邏輯的處理器。
G(Goroutine):其實本質上也是一種輕量級的線程。
GMP模型和PMG模型?
Goroutine 什么時候會發生阻塞?
PMG模型的 Goroutine 有那幾種狀態,線程有哪幾種狀態?
答:在PMG模型中 - M去搶占G的時候有個自旋和非自旋狀態
線程和協程占用的內存空間分別多少?
答:線程:固定的棧內存(通常為2MB左右)、協程:一個goroutine(協程)占用內存非常小 2 KB左右
如果一個 Goroutine 一直占用資源怎么辦?PMG模型是怎么解決這問題?
如果若干個線程中,其中一個線程發生了 OOM 會怎么樣?如果是 Goroutine 發生了 OOM會怎么樣?
如果若干個 Goroutine ,其中有個發生 panic 要怎么處理?
defer 可以捕獲到其 Goroutine 的子 Goroutine 發生的 panic嗎?
有統一的錯誤處理嗎,統一拋到一個函數處理?類似py的try except
反射了解過嗎?反射的原理是什么?
Golang 的鎖機制有了解過嗎? Mutex的鎖有哪幾種模式?Mutex 鎖底層如何實現? Mutex鎖能做自旋鎖嗎?
RWMutex(讀寫互斥鎖)了解嗎?使用什么場景?
Golang 是怎么實現 channel 的底層數據結構?
數據庫鎖機制
Redis 鎖機制、持久化AOF,主從模式、集群模式、哨兵模式
Mysql ORM
負載均衡算法
golang中級面試:
func main(){
var a uint = 1
var b uint = 2
fmt.Println(a-b)
// 如果操作系統是 32 位就是 2 的 32 次方 -1, 64位操作系統就是 2 的 64 次方 -1
// Go 是強類型語言,相當於uint 0-1,在計算機uint計算都是加法運算,相當於 0 + -1
// 負數的計算方式都會轉成補碼,-1的補碼就是所有位都是1,最終計算結果出來都是1的二進制
// uint識別的話就是當前當前位數的最大值
}
介紹下 rune 類型?
4. uint類型溢出
5. 介紹rune類型
6. 編程題:3個函數分別打印cat、dog、fish,要求每個函數都要起一個goroutine,按照cat、dog、fish順序打印在屏幕上100次。
7. 介紹一下channel,無緩沖和有緩沖區別
8. 是否了解channel底層實現,比如實現channel的數據結構是什么?
9. channel是否線程安全?
10. Mutex是悲觀鎖還是樂觀鎖?悲觀鎖、樂觀鎖是什么?
11. Mutex幾種模式?
12. Mutex可以做自旋鎖嗎?
13. 介紹一下RWMutex
14. 項目中用過的鎖?
15. 介紹一下線程安全的共享內存方式
16. 介紹一下goroutine
17. goroutine自旋占用cpu如何解決(go調用、gmp)
18. 介紹linux系統信號
19. goroutine搶占時機(gc 棧掃描)
20. Gc觸發時機
21. 是否了解其他gc機制
22. Go內存管理方式
23. Channel分配在棧上還是堆上?哪些對象分配在堆上,哪些對象分配在棧上?
24. 介紹一下大對象小對象,為什么小對象多了會造成gc壓力?
25. 項目中遇到的oom情況?
26. 項目中使用go遇到的坑?
27. 工作遇到的難題、有挑戰的事情,如何解決?
28. 如何指定指令執行順序?