为了账号安全,请及时绑定邮箱和手机立即绑定

Go goroutine 泄漏

Go goroutine 泄漏

Go
一只甜甜圈 2023-07-31 16:11:50
我尝试解决我的泄漏代码。但是向通道添加缓冲区并没有达到目的。我的代码package mainimport (    "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-routine 中的泄漏函数,.. 泄漏。在这篇文章之后,我预计通过向通道添加缓冲区,可以避免泄漏。
查看完整描述

1 回答

?
撒科打诨

TA贡献1934条经验 获得超2个赞

这里,在 Go Playground 中,是经过一些细微修改的原始代码:

  • 延迟减少,除了time.Sleep(5)变为time.Sleep(time.Second);

  • areturn被删除,因为它变得不必要;

  • afmt.Println被注释掉,因为 thereturn和未注释的fmt.Println都会go vet抱怨无法访问fmt.Println

  • 存储的通道errChang更改为无缓冲。

运行时,其输出为:

1
hola
2

(在 之前有一个小的延迟2),表明您在 function 中启动的匿名 goroutine 确实leaking仍在运行。

如果我们取消注释掉的注释fmt.Println,则输出为:

1
hola
6
1

(在final之前有同样的轻微延迟1)因为我们现在等待(然后打印)在return666channel中计算并发送的值errChang

如果我们保留注释掉的注释fmt.Println并使通道缓冲,则输出将变为:

1
hola
1

因为匿名 goroutine 现在能够将其值 (6) 推送到通道中。

通道本身以及存储在其中的单个值将被垃圾收集,因为此时没有对该通道的剩余引用。但请注意,仅仅使通道缓冲并不总是足够的。如果我们沿着通道发送两个值,程序将返回打印:

1
hola
2

因为匿名 goroutine 成功放入6通道,但随后也阻止了尝试放入42


查看完整回答
反对 回复 2023-07-31
  • 1 回答
  • 0 关注
  • 93 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信