版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013862108/article/details/88629715
goroutine 有以下几种方式被终止: 1。 当他完成了它的工作。 2。 因为不可恢复的错误, 它不能继续工作 3。 当他被告知 需要终止工作。 我们可以简单的使用前两种方法, 因为这两种方法隐含在你的算法中, 但"取消工作" 又是怎样工作的呢? 例如:这样情况: 子goroutine 是否该继续执行可能是以许多其他goroutine 状态的认知为基础的。 通常是 main goroutine 具有这种语境知识能够告诉其子goroutine 终止。 下面看一个 泄漏的例子/ (goroutine 没有进行死亡处理的例子)
func main() {
doWork := func(strings <-chan string) <-chan interface {} {
completed := make(chan interface{})
go func() {
defer fmt.Println("doWork exited.")
defer close(completed)
for s := range strings{
//做一些有趣的事
fmt.Println(s)
}
}()
return completed
}
doWork(nil)
//也许这里有其他操作需要执行
fmt.Println("Done.")
}
*/
/**
分析: doWork 的goroutine 在整个生命周期中都保留在内存中;显然不合理,传入的是nil 应该是更早的结束这个goroutine 才对。
怎么解决呢,使用 done channel
分析: doWork 的goroutine 在整个生命周期中都保留在内存中;显然不合理,传入的是nil 应该是更早的结束这个goroutine 才对。 怎么解决呢,使用 done channel
func main(){
doWork := func(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 :
return
}
}
}()
return terminated
}
done := make(chan interface{})
terminated := doWork(done, nil)
go func() {
//一秒后取消 dowork 里边的 goroutine
time.Sleep(1 * time.Second)
fmt.Println("Cancelling doWork goroutine...")
close(done)
}()
<-terminated
fmt.Println("Done.")
}
//Cancelling doWork goroutine...
//doWork exited.
//Done.
*/
/**
分析: 尽管我们给我们的字符串 channel 中传递了nil, 我们的goroutine仍然成功退出。 通过 1s 后 关闭doWork 中 goroutine 成功消除了我们的
goroutine 泄漏
分析: 尽管我们给我们的字符串 channel 中传递了nil, 我们的goroutine仍然成功退出。 通过 1s 后 关闭doWork 中 goroutine 成功消除了我们的 goroutine 泄漏 这个例子 是: doWork 的 goroutine 从某个channel(作为参数传进来) 中 for 读取 下面这个例子: doWork 中的goroutine 向某个channel() 中写入(for方式)数据
func main(){
newRandStream := func() <-chan int{
randStream := make(chan int)
go func() {
defer fmt.Println("newRandStream closure exited.")
defer close(randStream)
for{
randStream <- rand.Int()
}
}()
return randStream
}
randStream := newRandStream()
fmt.Println("3 random ints:")
for i:=1; i<=3; i++{
fmt.Printf("%d: %d\n", i, <-randStream)
}
}
//
//3 random ints:
//1: 5577006791947779410
//2: 8674665223082153551
//3: 6129484611666145821
*/
/**
问题: 在三次迭代后,我们的goroutine试图将下一个随机数发送到不需要的被读取的 channel. 我们没有告诉生产者它可以停止了。
解决方案: 像接收案例一样,为生产者提供一个通知他 退出 的 done channel:
问题: 在三次迭代后,我们的goroutine试图将下一个随机数发送到不需要的被读取的 channel. 我们没有告诉生产者它可以停止了。 解决方案: 像接收案例一样,为生产者提供一个通知他 退出 的 done channel:
func main(){
newRandStream := func(done <-chan interface{}) <-chan int {
randStream := make(chan int)
go func() {
defer fmt.Println("newRandStream closure exited. ")
defer close(randStream)
for{
select {
case randStream <-rand.Int() :
case <-done :
return
}
}
}()
return randStream
}
done := make(chan interface{})
randStream := newRandStream(done)
fmt.Println(" 3 random ints:")
for i:=1; i<=3; i++ {
fmt.Printf("%d: %d\n", i, <-randStream)
}
close(done)
//正在模拟进行的工作
time.Sleep(1 * time.Second)
}
*/
/**
为了goroutine 不泄漏, 约定: 如果goroutine 负责创建 goroutine,他也负责 确保可以停止 goroutine
*/
为了goroutine 不泄漏, 约定: 如果goroutine 负责创建 goroutine,他也负责 确保可以停止 goroutine