for select 里使用 return 阻塞问题
在 golang 并发编程中,使用 for select 语句处理多个通道提供了便捷的方式。然而,当在 for select 的 case 分支中使用 return 语句时,可能会导致阻塞。
考虑以下示例代码:
package main import ( "fmt" "sync" ) type cache struct { ch chan int } var ( _cache *cache _once sync.once ) func newcache() *cache { _once.do(func() { _cache = &cache{ ch: make(chan int), } _cache.monitor() }) return _cache } func (c *cache) push(x int) { c.ch <- x } func (c *cache) monitor() { go func() { for { select { case result, ok := <-c.ch: if ok { fmt.println(result) } default: fmt.println("no data") } } }() } func main() { c := newcache() c.push(1) c.push(2) c.push(3) } ```` 在这个示例中,`monitor()` 函数启动了一个协程,该协程不断从 `_cache.ch` 通道中接收数据。然而,当我们尝试通过 `c.push` 函数向通道发送数据时,请求会一直阻塞。 了解这种情况的原因至关重要:当我们在 `for select` 语句的 `case` 分支中使用 `return` 语句时,这不仅会退出当前 `case` 分支,还会退出整个 `for select` 循环。结果,协程将终止,并且通道将不再被消费,导致请求阻塞。 为了解决此问题,我们可以使用 `break` 或 `continue` 语句来退出当前 `case` 分支,而不是使用 `return` 语句。这将使 `for select` 循环继续,并允许协程继续接收数据。 修改后的代码如下:
func (c *cache) monitor() {
立即学习“go语言免费学习笔记(深入)”;
go func() { for { select { case result, ok := <-c.ch: if ok { fmt.Println(result) } else { break // 退出当前 case 分支 } default: fmt.Println("No data") } } }()
}
以上就是Golang 并发编程中:为什么在 for select 的 case 分支中使用 return 会导致阻塞?的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号