gpt4 book ai didi

go - 为什么这个 goroutine 会泄漏?

转载 作者:IT王子 更新时间:2023-10-29 02:28:14 25 4
gpt4 key购买 nike

我正在阅读“Go 中的并发”并发现了这个 goroutine 泄漏的例子:

func main() {

var wg sync.WaitGroup

doWork := func(strings <-chan string) <-chan interface{} {
completed := make(chan interface{})
go func() {
defer fmt.Println("doWork exited.")
defer close(completed)
defer wg.Done()
fmt.Println("a")
for s := range strings {
fmt.Println(s)
}
fmt.Println("b")
}()
return completed
}

wg.Add(1)
doWork(nil)
fmt.Println("Waiting")
wg.Wait()

fmt.Println("Done.")
}

The strings channel will never gets any strings written onto it, and the goroutine containing doWork will remain in memory for the life time of process.

我不明白 - 为什么?

我如何理解这段代码:

  • 由于 stringsnil range - 循环刚刚被跳过。作为任何超过 nil 的范围:

    slice := []int{10, 20, 30, 40, 50}
    slice = nil
    for i := range slice {
    fmt.Println(i)
    }
    fmt.Println("Done")
  • fmt.Println("doWork exited.")会被执行

  • close(completed)将被执行

但我看到它是那样工作的。为什么?

最佳答案

As strings is nil range-loop just skipped.

这个假设是不正确的。在 Go 中,从 nil channel 读取总是会阻塞。这是在 language specification 中定义的(感谢@peterSO 挖掘出链接):

Receiving from a nil channel blocks forever.

还有 a post on the Go Design Patterns blog进一步阐述了这种行为,并强调了它有用的一些情况。

无论如何,这个行为可以很容易地用一个最小的例子重现(playground):

func main() {
var s chan string
<- s
}

这个程序永远不会完成(在 Playground 上,它会崩溃,all goroutines are asleep - deadlock)。

因为从 nil channel 读取(在您的示例中,strings)将阻塞(永远,因为没有任何东西可以写入 nil channel ),doWork goroutine 永远不会完成,因此会泄漏。

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

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