goroutine终止方式
goroutine运行时不会被垃圾回收,所以即使goroutine占用内容非常少,我们也需要注意goroutine泄漏问题,goroutine的终止方式有3种
- 完成了工作
- 遇到不可恢复的错误
- 被告知结束工作
泄漏的示例
package main
import "fmt"
func main() {
doWork := func(ch <-chan interface{}) <-chan interface{} {
chRst := make(chan interface{})
go func() {
defer close(chRst)
// 如果ch为nil, 则会一直阻塞,该方法不会完成
for i := range ch {
fmt.Println(i)
}
}()
return chRst
}
chRst := doWork(nil)
fmt.Println(<-chRst)
}
怎样防止泄漏
上述的例子没有完成工作,并且没有致命的错误,所以就只能需要有渠道通知他来结束工作,所以我们引入了一个done的channel来通知该goroutine来退出工作,示例如下
package main
import "fmt"
import "time"
func main() {
doWork := func(done, ch <-chan interface{}) <-chan interface{} {
chRst := make(chan interface{})
go func() {
defer close(chRst)
for {
select {
case <-done:
// 如果done关闭,则退出该goroutine
return
case s := <-ch:
fmt.Println(s)
}
}
fmt.Println("goroutine exit")
}()
return chRst
}
done := make(chan interface{})
chRst := doWork(done, nil)
go func() {
time.Sleep(time.Second * 2)
close(done)
}()
fmt.Println(<-chRst)
}