共计 1306 个字符,预计需要花费 4 分钟才能阅读完成。
golang 面试官:for select 时,如果通道曾经敞开会怎么样?如果 select 中只有一个 case 呢?
问题
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. 怎么样能力不读敞开后通道
x, ok := <-c
返回的值里第一个 x 是通道内的值,ok
是指通道是否敞开,当通道被敞开后,ok
则返回false
,因而能够依据这个进行操作。读一个曾经敞开的通道为什么会呈现 false,能够看我之前的 对曾经敞开的的 chan 进行读写,会怎么样?为什么?。- 当返回的
ok
为false
时,执行c = nil
将通道置为nil
,相当于读一个未初始化的通道,则会始终阻塞。至于为什么读一个未初始化的通道会呈现阻塞,能够看我的另一篇 对未初始化的的 chan 进行读写,会怎么样?为什么?。select
中如果任意某个通道有值可读时,它就会被执行,其余被疏忽。则select
会跳过这个阻塞case
,能够解决一直读已敞开通道的问题。
3. 如果 select 里只有一个曾经敞开的 case,会怎么样?
- 能够看出只有一个
case
的状况下,则会死循环
。 - 那如果像下面一个
case
那样,把通道置为nil
就能解决问题了吗?
4.select 里只有一个曾经敞开的 case,置为 nil,会怎么样?
- 第一次读取
case
能读到通道里的10
- 第二次读取
case
能读到通道曾经敞开的信息。此时将通道置为nil
- 第三次读取
case
时 main 协程会被阻塞,此时整个过程没有其余流动的协程了,过程deadlock
总结
select
中如果任意某个通道有值可读时,它就会被执行,其余被疏忽。- 如果没有
default
字句,select
将有可能阻塞,直到某个通道有值能够运行,所以select
里最好有一个default
,否则将有始终阻塞的危险。
文章举荐:
- golang 面试题:对曾经敞开的的 chan 进行读写,会怎么样?为什么?
- golang 面试题:对未初始化的的 chan 进行读写,会怎么样?为什么?
- golang 面试题:reflect(反射包)如何获取字段 tag?为什么 json 包不能导出公有变量的 tag?
- golang 面试题:json 包变量不加 tag 会怎么样?
- golang 面试题:怎么防止内存逃逸?
- golang 面试题:简略聊聊内存逃逸?
- golang 面试题:字符串转成 byte 数组,会产生内存拷贝吗?
- golang 面试题:翻转含有
中文、数字、英文字母
的字符串 - golang 面试题:拷贝大切片肯定比小切片代价大吗?
- golang 面试题:能说说 uintptr 和 unsafe.Pointer 的区别吗?
如果你想每天学习一个知识点?
正文完