在这篇关于例程泄漏( https://www.ardanlabs.com/blog/2018/11/goroutine-leaks-the-forgotten-sender.html )的文章之后,我试图解决我的代码泄漏问题.但是在通道中添加一个缓冲器,它并没有达到这个目的。
我的代码
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
fmt.Println(runtime.NumGoroutine())
leaking()
time.Sleep(5)
fmt.Println(runtime.NumGoroutine())
}
func leaking() {
errChang := make(chan int, 1)
go func() {
xx := return666()
errChang <- xx
}()
fmt.Println("hola")
return
fmt.Println(<-errChang)
}
func return666() int {
time.Sleep(time.Second * 1)
return 6
}我的初始代码没有使用缓冲区,导致泄漏函数中的go例程..为了泄密。在帖子之后,我希望通过在通道中添加一个缓冲区,可以避免泄漏。
发布于 2019-10-28 21:46:36
在这里,在围棋游乐场是您的原始代码,只需稍作修改:
time.Sleep(5)变成time.Sleep(time.Second)外,延迟也减少了;return被删除,因为它变得没有必要;fmt.Println被注释掉,因为对于return和未注释的fmt.Println,go vet抱怨不可访问的fmt.Println;errChang中的信道将更改为无缓冲。当运行时,它的输出是:
1
hola
2(在2之前有一个小延迟),这表明您在函数leaking中启动的匿名goroutine仍然在运行。
如果我们使用fmt.Println,输出是:
1
hola
6
1(在最后的1之前也有同样的轻微延迟),因为我们现在等待(然后打印)在return666中计算的值并通过通道errChang发送。
如果我们使用注释掉并使信道缓冲。,输出将变成:
1
hola
1因为匿名的goroutine现在能够将它的值(6)推到通道中。
通道本身将与存储在其中的单个值一起被垃圾收集,因为此时不再有对通道的引用。但是,请注意,简单地使通道缓冲并不总是足够的。如果我们使用向通道发送两个值,程序将返回到打印:
1
hola
2由于匿名的goroutine成功地将6放入了通道,但同时也阻止了试图将42放入通道。
https://stackoverflow.com/questions/58597199
复制相似问题