上下文取消后,
在 go 语言中,使用 context.context 包可以实现协程间通信和取消。当 context 被取消后,
这是因为
导致该问题的一个示例
以下代码演示了该问题:
package main import ( "context" "fmt" ) func gen(ctx context.context) <-chan interface{} { ch := make(chan interface{}) go func() { n := 0 for { select { case <-ctx.done(): fmt.println("done") default: n += 1 ch <- n } } }() return ch } func main() { ctx, cancel := context.withcancel(context.background()) for n := range gen(ctx) { fmt.println(n) if n == 5 { break } } defer cancel() }
在这种情况下,for循环将在读取到第六个元素之前一直运行。这意味着,当cancel()被调用时,第六个元素已经准备好了。因此,
解决方法
可以通过关闭通道来解决此问题。当上下文被取消时,关闭通道将导致
以下代码显示了改进后的示例:
package main import ( "context" "fmt" ) func gen(ctx context.Context) <-chan interface{} { ch := make(chan interface{}) go func() { n := 0 for { select { case <-ctx.Done(): fmt.Println("done") close(ch) // 关闭通道,range结束 return default: n += 1 ch <- n } } }() return ch } func main() { ctx, cancel := context.WithCancel(context.Background()) for n := range gen(ctx) { fmt.Println(n) if n == 5 { cancel() // break不能break,否则没有从ch中读取,就会一直阻塞在ch<-n } } }
这样,无论第六个元素是否已经准备好,
以上就是Go 语言中,当 context 被取消后,`的详细内容,更多请关注php中文网其它相关文章!
版权声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系 yyfuon@163.com