在Go语言中,开启一个“线程”只需使用go关键字及一个go函数(
goroutine),goroutine是廉价且易于创建的,goroutine不会被运行时垃圾回收,如何确保goroutine被清理?for...select...语句提供了可行的解决方案。
一、for...select...语句
for...select语句从一组channel中选择可用的进行操作,对于多个可用的channel,select语句会以随机的方式选择其中一个channel进行操作。- 在子
goroutine中的for...select...中添加只读channel(done),对应的处理为return,即goroutine退出,在父goroutine中关闭done,使done可用,子goroutine就会退出。
二、示例代码
package main
import (
"fmt"
"time"
)
func doWork(
done <-chan interface{},
strings <-chan string) <-chan interface{} {
terminated := make(chan interface{})
go func() {
defer fmt.Println("doWork exited!")
defer close(terminated)
for {
select {
case s := <-strings:
fmt.Println(s)
case <-done: // 只读channel,未关闭或未接收数据时不可用(case不选择)
return
}
}
}()
return terminated
}
func main() {
done := make(chan interface{})
strings := make(chan string)
terminated := doWork(done, strings)
go func() {
time.Sleep(time.Second)
fmt.Println("Canceling doWork goroutine...")
close(done) // 关闭done channel之后,在子goroutine中的select语句会选择退出
}()
<-terminated // 阻塞主goroutine
fmt.Println("Done!")
}
// 运行结果:
// Canceling doWork goroutine...
// doWork exited!
// Done!
- 最终子
goroutine在1 s后退出。在父goroutine中,对donechannel只进行创建和关闭操作。 - 在
done未关闭之前,子goroutine继续执行自身的任务。
本文介绍了Go语言中如何通过for...select...语句管理goroutine,特别是利用只读channel来确保goroutine的优雅退出。示例代码展示了一个使用done channel关闭并退出goroutine的场景,当done被关闭时,子goroutine接收到信号后会终止执行。这种方法提供了一种有效控制goroutine生命周期的方法。
5万+

被折叠的 条评论
为什么被折叠?



