gpt4 book ai didi

go - 为什么 goroutine 会泄漏

转载 作者:IT王子 更新时间:2023-10-29 01:22:50 25 4
gpt4 key购买 nike

我读了Twelve Go Best Practices并在第 30 页遇到有趣的例子。

func sendMsg(msg, addr string) error {
conn, err := net.Dial("tcp", addr)
if err != nil {
return err
}
defer conn.Close()
_, err = fmt.Fprint(conn, msg)
return err
}

func broadcastMsg(msg string, addrs []string) error {
errc := make(chan error)
for _, addr := range addrs {
go func(addr string) {
errc <- sendMsg(msg, addr)
fmt.Println("done")
}(addr)
}

for _ = range addrs {
if err := <-errc; err != nil {
return err
}
}
return nil
}

func main() {
addr := []string{"localhost:8080", "http://google.com"}
err := broadcastMsg("hi", addr)

time.Sleep(time.Second)

if err != nil {
fmt.Println(err)
return
}
fmt.Println("everything went fine")
}

程序员提到,上面的代码发生了这种情况:

the goroutine is blocked on the chan write
the goroutine holds a reference to the chan
the chan will never be garbage collected

为什么goroutine会卡在这里?主线程被阻塞,直到它从 goroutine 接收到数据。在它继续 for 循环之后。不是吗?

为什么 errc chan 永远不会被垃圾回收?因为我没有关闭 channel ,goroutine 结束后?

最佳答案

我看到的一个问题是在 goroutines 启动后 broadcastMsg() 中:

for _ = range addrs {
if err := <-errc; err != nil {
return err
}
}

如果从 errc 接收到非 nil errorbroadcastMsg() 会立即返回该错误并且不会从 channel 接收更多的值,这意味着更多的 goroutines 永远不会被解锁,因为 errc 是无缓冲的。

可能的修复

一个可能的解决方法是使用一个缓冲 channel ,它足够大,不会阻塞任何 goroutines,在这种情况下:

errc := make(chan error, len(addrs))

或者即使从 channel 接收到非nil error,仍然继续接收与在其上发送的 goroutines 一样多的次数:

var errRec error
for _ = range addrs {
if err := <-errc; err != nil {
if errRec == nil {
errRec = err
}
}
}
return errRec

或如 slide #33 上的链接谈话中所述: 使用“退出” channel 来防止启动的 goroutines 在 broadcastMsg() 完成/返回后保持阻塞状态。

关于go - 为什么 goroutine 会泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29892950/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com