golang面试题(对未初始化的的chan进行读写,会怎么样(为什么?))

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)"
【golang面试题(对未初始化的的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)"

    推荐阅读