? ? ? ? 雖然go語言使用起來方便簡單抹蚀,但他有很多特性是比較與眾不同的,在不了解的情況下,編碼時(shí)候就會(huì)產(chǎn)生很多莫名其妙的bug暑劝。
channel
????????這里的channel默認(rèn)是無緩沖的,但是有三個(gè)線程往里面寫萨蚕,而函數(shù)返回的時(shí)候只從中讀取了一個(gè)靶草,根據(jù)channel的特性,另外兩個(gè)線程(go routine 個(gè)人別稱 線程)中岳遥,另外兩個(gè)線程會(huì)一直阻塞在ch <- true 這一行奕翔,造成資源泄漏(內(nèi)存漲)。
解決辦法
????????有兩個(gè)解決辦法浩蓉,第一種使用select加上default的辦法派继,這樣宾袜,當(dāng)channel無法寫入的時(shí)候,就會(huì)觸發(fā)default退出驾窟。
????????另一個(gè)辦法是創(chuàng)建channel的時(shí)候庆猫,容量足夠大,大于等于3绅络,使得寫入不阻塞月培。
go routine
????????以為會(huì)輸出1,2恩急,3 實(shí)際卻輸出了3杉畜,3,3衷恭,原因是V這個(gè)變量是同一個(gè)地址重復(fù)使用此叠,三次循環(huán) &V 的地址都是一樣的,只是V的值改變了随珠,而GetId()函數(shù)的調(diào)用是用指針是調(diào)用的灭袁,所以船體給go routine的是V的地址,三次都一樣牙丽。然而go routine是異步開啟的简卧,循環(huán)執(zhí)行太快導(dǎo)致三個(gè)go routine得到的該地址值是最后一個(gè)了
解決辦法
????????如果在gov.GetId() 之后加上足夠時(shí)間的sleep()讓該 routine 建立起來,則可以避免這樣的問題烤芦。
????????或者先用一個(gè)臨時(shí)變量存儲(chǔ)v的值举娩,再用臨時(shí)變量開啟routine
range
????????原本以為在 循環(huán)剛開始的時(shí)候,把a(bǔ)rr[1]的值改成10后构罗,第二次循環(huán)的時(shí)候v會(huì)輸出 10铜涉,結(jié)果arr[1]的值確實(shí)是改了,而 v 依舊輸出是20遂唧。
????????原因是如果是數(shù)組等非指針類型芙代,會(huì)在循環(huán)前復(fù)制一份,循環(huán)的時(shí)候使用的是復(fù)制的值盖彭。(channel/map/slice/指針數(shù)組等不會(huì)這樣)
解決辦法
????????盡量使用指針數(shù)組或者切片(slice)纹烹。
slice
????????同樣是去掉第二個(gè)元素,用函數(shù)的方式卻跟預(yù)料的不一樣召边。
????????原因:實(shí)際上铺呵,切片作為參數(shù)的時(shí)候,雖然內(nèi)容是指針隧熙,切片本身是拷貝片挂,就是說函數(shù)內(nèi)外 &arr 的地址不一樣,但 &arr[n] 里面的元素的地址是一樣的, 所以函數(shù)外的arr長度并沒有減少音念。
解決辦法
????????使用返回值重新賦值的方式沪饺。