image
問題
對(duì)未初始化的的chan
進(jìn)行讀寫代芜,會(huì)怎么樣?為什么浓利?
怎么答
讀寫未初始化的chan
都會(huì)阻塞挤庇。
舉例
1.寫未初始化的chan
package main
// 寫未初始化的chan
func main() {
var c chan int
c <- 1
}
// 輸出結(jié)果
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send (nil chan)]:
main.main()
/Users/admin18/go/src/code.byted.org/linzhaolun/repos/main.go:6 +0x36
注意這個(gè)chan send (nil chan)
,待會(huì)會(huì)提到贷掖。
2.寫讀未初始化的chan
package main
import "fmt"
// 讀未初始化的chan
func main() {
var c chan int
num, ok := <-c
fmt.Printf("讀chan的協(xié)程結(jié)束, num=%v, ok=%v\n", num, ok)
}
// 輸出結(jié)果
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive (nil chan)]:
main.main()
/Users/admin18/go/src/code.byted.org/linzhaolun/repos/main.go:6 +0x46
注意這個(gè)chan receive (nil chan)
嫡秕,待會(huì)也會(huì)提到。
多問一句
關(guān)于chan
的面試題非常多苹威,這個(gè)是比較常見的其中一個(gè)昆咽。但多問一句:為什么對(duì)未初始化的chan
就會(huì)阻塞呢?
1.對(duì)于寫的情況
//在 src/runtime/chan.go中
func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
if c == nil {
// 不能阻塞牙甫,直接返回 false掷酗,表示未發(fā)送成功
if !block {
return false
}
gopark(nil, nil, waitReasonChanSendNilChan, traceEvGoStop, 2)
throw("unreachable")
}
// 省略其他邏輯
}
- 未初始化的
chan
此時(shí)是等于nil
,當(dāng)它不能阻塞的情況下窟哺,直接返回false
泻轰,表示寫chan
失敗 - 當(dāng)
chan
能阻塞的情況下,則直接阻塞gopark(nil, nil, waitReasonChanSendNilChan, traceEvGoStop, 2)
, 然后調(diào)用throw(s string)
拋出錯(cuò)誤,其中waitReasonChanSendNilChan
就是剛剛提到的報(bào)錯(cuò)"chan send (nil chan)"
2. 對(duì)于讀的情況
//在 src/runtime/chan.go中
func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool) {
//省略邏輯...
if c == nil {
if !block {
return
}
gopark(nil, nil, waitReasonChanReceiveNilChan, traceEvGoStop, 2)
throw("unreachable")
}
//省略邏輯...
}
- 未初始化的
chan
此時(shí)是等于nil
且轨,當(dāng)它不能阻塞的情況下浮声,直接返回false
,表示讀chan
失敗 - 當(dāng)
chan
能阻塞的情況下旋奢,則直接阻塞gopark(nil, nil, waitReasonChanReceiveNilChan, traceEvGoStop, 2)
, 然后調(diào)用throw(s string)
拋出錯(cuò)誤,其中waitReasonChanReceiveNilChan
就是剛剛提到的報(bào)錯(cuò)"chan receive (nil chan)"