跳至主要內容

golang面试官:for select时,如果通道已经关闭会怎么样?如果select中只有一个case呢?

小白debug大约 3 分钟

问题

for循环select时,如果通道已经关闭会怎么样?如果select中的case只有一个,又会怎么样?

怎么答

  • for 循环select时,如果其中一个 case 通道已经关闭,则每次都会执行到这个 case。
  • 如果 select 里边只有一个 case,而这个 case 被关闭了,则会出现死循环。

解释

1.for 循环里被关闭的通道

  • c通道是一个缓冲为0的通道,在main开始时,启动一个协程对c通道写入10,然后就关闭掉这个通道。
  • main中通过 x, ok := <-c 接受通道c里的值,从输出结果里看出,确实从通道里读出了之前塞入通道的10,但是在通道关闭后,这个通道一直能读出内容。

2.怎么样才能不读关闭后通道

3.如果 select 里只有一个已经关闭的 case,会怎么样?

  • 可以看出只有一个case的情况下,则会死循环
  • 那如果像上面一个case那样,把通道置为nil就能解决问题了吗?

4.select 里只有一个已经关闭的 case,置为 nil,会怎么样?

  • 第一次读取case能读到通道里的10
  • 第二次读取case能读到通道已经关闭的信息。此时将通道置为nil
  • 第三次读取case时 main 协程会被阻塞,此时整个进程没有其他活动的协程了,进程deadlock

总结

  • select中如果任意某个通道有值可读时,它就会被执行,其他被忽略。
  • 如果没有default字句,select将有可能阻塞,直到某个通道有值可以运行,所以select里最好有一个default,否则将有一直阻塞的风险。

参考文章: