Go goroutines 泄漏
Go goroutines leaking
在 post 关于 go-routines 泄漏 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
}
我的初始代码没有使用缓冲区,导致 leaking 函数中的 go-routine,.. 泄漏。在 post 之后,我预计通过向通道添加缓冲区,可以避免泄漏。
Here, in the Go Playground,是您的原始代码,稍作修改:
- 延迟减少,除了
time.Sleep(5)
变为 time.Sleep(time.Second)
;
- a
return
已删除,因为它变得不必要了;
- a
fmt.Println
被注释掉了,因为 return
和未注释的 fmt.Println
,go vet
抱怨无法到达 fmt.Println
;
- 存储在
errChang
中的频道更改为无缓冲。
当运行时,其输出为:
1
hola
2
(在 2
之前有一个小的延迟),表明你在函数 leaking
中启动的匿名 goroutine 仍然是 运行ning.
如果我们uncomment the commented-out fmt.Println
,输出是:
1
hola
6
1
(在最终 1
之前有同样的轻微延迟)因为我们现在等待(然后打印)在 return666
中计算并通过通道 errChang
发送的值。
如果我们keep the commented-out fmt.Println
commented out and make the channel buffered,输出变为:
1
hola
1
因为匿名 goroutine 现在可以将其值 (6) 推送到通道中。
通道本身以及存储在其中的单个值将被垃圾回收,因为此时没有对通道的剩余引用。但是请注意,简单地使通道缓冲并不总是足够的。如果我们send two values down the channel,程序returns打印:
1
hola
2
因为匿名 goroutine 成功地将 6
放入通道,但随后阻止尝试将 42
也放入。
在 post 关于 go-routines 泄漏 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
}
我的初始代码没有使用缓冲区,导致 leaking 函数中的 go-routine,.. 泄漏。在 post 之后,我预计通过向通道添加缓冲区,可以避免泄漏。
Here, in the Go Playground,是您的原始代码,稍作修改:
- 延迟减少,除了
time.Sleep(5)
变为time.Sleep(time.Second)
; - a
return
已删除,因为它变得不必要了; - a
fmt.Println
被注释掉了,因为return
和未注释的fmt.Println
,go vet
抱怨无法到达fmt.Println
; - 存储在
errChang
中的频道更改为无缓冲。
当运行时,其输出为:
1
hola
2
(在 2
之前有一个小的延迟),表明你在函数 leaking
中启动的匿名 goroutine 仍然是 运行ning.
如果我们uncomment the commented-out fmt.Println
,输出是:
1
hola
6
1
(在最终 1
之前有同样的轻微延迟)因为我们现在等待(然后打印)在 return666
中计算并通过通道 errChang
发送的值。
如果我们keep the commented-out fmt.Println
commented out and make the channel buffered,输出变为:
1
hola
1
因为匿名 goroutine 现在可以将其值 (6) 推送到通道中。
通道本身以及存储在其中的单个值将被垃圾回收,因为此时没有对通道的剩余引用。但是请注意,简单地使通道缓冲并不总是足够的。如果我们send two values down the channel,程序returns打印:
1
hola
2
因为匿名 goroutine 成功地将 6
放入通道,但随后阻止尝试将 42
也放入。