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

9號 · · 723 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

image

问题

未初始化的的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)"

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

723 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传