乐趣区

关于golang:Go-Quiz-从Go面试题看channel在select场景下的注意事项

面试题

这是 Go Quiz 系列中对于 channel 的第 2 篇,波及 channel 被 close 后的个性,以及在 selectchannel一起应用时的注意事项。

这道题目来源于 Google 的工程师 Valentin Deleplace。

package main

import "fmt"

func main() {data := make(chan int)
    shutdown := make(chan int)
    close(shutdown)
    close(data)

    select {
    case <-shutdown:
        fmt.Print("CLOSED,")
    case data <- 1:
        fmt.Print("HAS WRITTEN,")
    default:
        fmt.Print("DEFAULT,")
    }
}
  • A: 进入 default 分支,打印 ”DEFAULT, “
  • B: 进入 shutdown 分支,打印 ”CLOSED, “
  • C: 进入 data 分支,打印 ”HAS WRITTEN, “
  • D: 程序会 panic
  • E: 程序可能 panic,也可能打印 ”CLOSED, “

这道题次要考查以下知识点:

  • channel被敞开后,从 channel 接收数据和往 channel 发送数据会有什么后果?
  • select的运行机制是怎么的?

解析

  1. 对于无缓冲区的 channel,往channel 发送数据和从 channel 接收数据都会阻塞。
  2. 对于 nil channel 和有缓冲区的channel,收发数据的机制如下表所示:

    channel nil 空的 非空非满 满了
    往 channel 发送数据 阻塞 发送胜利 发送胜利 阻塞
    从 channel 接收数据 阻塞 阻塞 接管胜利 接管胜利
    敞开 channel panic 敞开胜利 敞开胜利 敞开胜利
  3. channel被敞开后:

    • 往被敞开的 channel 发送数据会触发 panic。
    • 从被敞开的 channel 接收数据,会先读完 channel 里的数据。如果数据读完了,持续从 channel 读数据会拿到 channel 里存储的元素类型的零值。

      data, ok := <- c 

      对于下面的代码,如果 channel c敞开了,持续从 c 里读数据,当 c 里还有数据时,data就是对应读到的值,ok的值是 true。如果c 的数据曾经读完了,那 data 就是零值,ok的值是false

    • channel被敞开后,如果再次敞开,会引发 panic。
  4. select的运行机制如下:

    • 选取一个可执行不阻塞的 case 分支,如果多个 case 分支都不阻塞,会随机选一个 case 分支执行,和 case 分支在代码里写的程序没关系。
    • 如果所有 case 分支都阻塞,会进入 default 分支执行。
    • 如果没有 default 分支,那 select 会阻塞,直到有一个 case 分支不阻塞。

依据以上规定,本文最开始的题目,在运行的时候

  • data 和 shutdown 这 2 个 channel 都被敞开了。
  • 对于敞开的 channel,从 channel 里接收数据,拿到的是 channel 的存储的元素类型的零值,因而 case <-shutdown 这个 case 分支不会阻塞。
  • 对于敞开的 channel,向其发送数据会引发 panic,因而 case data <- 1 这个 case 分支不会阻塞,会引发 panic。
  • 因而这个 select 语句执行的时候,2 个 case 分支都不会阻塞,都可能执行到。如果执行的是 case <-shutdown 这个 case 分支,会打印 ”CLOSED, “。如果执行的是 case data <- 1 这个 case 分支,会导致程序 panic。

因而本题的答案是E

加餐

能够回顾 Go quiz 系列中对于 channel 的第一道题目,加深对 channel 的了解。

题目链接地址:channel 面试题和注意事项

开源地址

文章和示例代码开源地址在 GitHub: https://github.com/jincheng9/…

公众号:coding 进阶

集体网站:https://jincheng9.github.io/

知乎:https://www.zhihu.com/people/…

References

  • https://twitter.com/val_delep…
  • https://github.com/jincheng9/…
  • https://github.com/jincheng9/…
  • https://github.com/jincheng9/…
退出移动版