golang面試題:對未初始化的的chan進行讀寫,會怎麼樣?爲什麼?

問題

未初始化的的chan進行讀寫,會怎麼樣?爲什麼?

怎麼答

讀寫未初始化chan都會阻塞

舉例

1.寫未初始化的chan
package main
// 寫未初始化的chan
func main() {
	var c chan int
	c <- 1
}
// 輸出結果
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

注意這個chan send (nil chan),待會會提到。

2.寫讀未初始化的chan
package main
import "fmt"
// 讀未初始化的chan
func main() {
	var c chan int
	num, ok := <-c
	fmt.Printf("讀chan的協程結束, num=%v, ok=%v\n", num, ok)
}
// 輸出結果
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

注意這個chan receive (nil chan),待會也會提到。

多問一句

關於chan的面試題非常多,這個是比較常見的其中一個。但多問一句:爲什麼對未初始化的chan就會阻塞呢?

1.對於寫的情況

//在 src/runtime/chan.go中
func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
	if c == nil {
      // 不能阻塞,直接返回 false,表示未發送成功
      if !block {
        return false
      }
      gopark(nil, nil, waitReasonChanSendNilChan, traceEvGoStop, 2)
      throw("unreachable")
	}
  // 省略其他邏輯
}
  • 未初始化的chan此時是等於nil,當它不能阻塞的情況下,直接返回 false,表示寫 chan 失敗
  • chan能阻塞的情況下,則直接阻塞 gopark(nil, nil, waitReasonChanSendNilChan, traceEvGoStop, 2), 然後調用throw(s string)拋出錯誤,其中waitReasonChanSendNilChan就是剛剛提到的報錯"chan send (nil chan)"

2. 對於讀的情況

//在 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此時是等於nil,當它不能阻塞的情況下,直接返回 false,表示讀 chan 失敗
  • chan能阻塞的情況下,則直接阻塞 gopark(nil, nil, waitReasonChanReceiveNilChan, traceEvGoStop, 2), 然後調用throw(s string)拋出錯誤,其中waitReasonChanReceiveNilChan就是剛剛提到的報錯"chan receive (nil chan)"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章