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

a92f09778adfcd8d9a0b1f578bea1262.png

问题

未初始化的的 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=%vn", 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)"

文章推荐:

  • golang 面试题:​reflect(反射包)如何获取字段 tag​?为什么 json 包不能导出私有变量的 tag?
  • golang 面试题:json 包变量不加 tag 会怎么样?
  • golang 面试题:怎么避免内存逃逸??
  • golang 面试题:简单聊聊内存逃逸?
  • golang 面试题:字符串转成 byte 数组,会发生内存拷贝吗?
  • golang 面试题:翻转含有中文、数字、英文字母的字符串
  • golang 面试题:拷贝大切片一定比小切片代价大吗?
  • golang 面试题:能说说 uintptr 和 unsafe.Pointer 的区别吗?

如果你想每天学习一个知识点,关注我的【公】【众】【号】【golang 小白成长记】。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值