Golang Go语言中 select 的一个疑问

func f() {
    for {
    	select {
        case <-stopCh:
            return
        case <-t.C():
            // do something
        }
    }
}

如果 定时器 和 stopCh 同时触发,然后随机执行了 定时器的代码,那么这个函数还会退出吗


Golang Go语言中 select 的一个疑问
9 回复

下一次循环就退出了

更多关于Golang Go语言中 select 的一个疑问的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果随机选择了执行定时器的代码,那么在这次 select 语句执行完毕之后,函数会再次进入 select 语句的等待。如果此时 stopCh 依然是可用状态,那么下一次 select 可能会选择 stopCh 的案例,导致函数返回并退出。但如果 stopCh 在下一次选择前不再触发,函数将继续运行直到其中一个案例再次被触发。

stopCh 的触发是外部 close(stopCh)

建议 do something 逻辑用异步,不然容易出现 stopCh 无法 return 的情况

#3 close 了还是可以一直读的

当然会,golang 声称随机选择是公平的,所以不会一致执行定时器。总会随机到 stopCh 。如果处理的时间很长,为了比来多执行一次,我认为应该加一些逻辑优先判断当前退出状态,外边补一层 select stopCh

了解了,close 之后的 channel 依然可读

这个特性确实很麻烦,所以我为了保证及时退出,都是在 t.C()这种业务分支下面再加一个 select 来判断 stopCh ,保证最多只执行一次就退出

当然,以下是对关于Golang中select语句疑问的专业回复:


在Golang中,select语句用于处理多个通信操作,它会阻塞,直到其中一个通信可以进行。这是并发编程中一个非常有用的特性,特别是在需要等待多个通道(channel)操作时。

关于select的疑问,可能主要集中在以下几个方面:

  1. 如何选择通道select会随机选择一个可以立即进行通信的通道。如果有多个通道都准备好,select会随机选择其中一个,这是非确定性的。

  2. 默认分支select语句中可以包含一个不带任何通道操作的默认分支(default case)。如果存在默认分支,且没有其他通道准备好,select会立即执行默认分支,而不会阻塞。

  3. 通道关闭:当select中的某个通道被关闭时,对应的接收操作会成功并返回通道类型的零值,而不会永久阻塞。

  4. 超时处理:通过结合time.Aftertime.AfterFunc,可以实现超时处理。例如,可以设置一个超时通道,在指定时间后发送信号,从而避免select无限期阻塞。

  5. 嵌套使用select语句可以嵌套使用,以处理更复杂的通信模式。

总之,select是Golang并发编程中的一个强大工具,它允许程序在等待多个通道操作时保持灵活性和响应性。理解select的工作原理和特性,对于编写高效、可维护的并发程序至关重要。


希望这个回复能解答你的疑问!

回到顶部