当匿名函数在 golang 中永远等待通道时会发生什么?

What happens when an anonymous function waits on channel forever in golang?

我有一个函数可以创建一个没有缓冲区的通道。此函数继续创建其他几个写入所述通道的并发匿名函数。然后函数继续等待通道上的输入,然后 returns 值。

见下面的例子

package main

import (
    "time"
    "fmt"
    "strconv"
    "math/rand"
)

func main() {
    for{
        text := foo()
        fmt.Println(text)
        time.Sleep(time.Second)
    }

}

func foo() string {    
    ch := make(chan string)
    for i := 0; i < 10; i++ {
        // Create some threads
        go func(i int) {
            time.Sleep(time.Duration(rand.Intn(1000))*time.Millisecond)
            ch <- strconv.Itoa(i)
        }(i)
    }
    return <- ch
}

尽管整个函数(示例中的 foo)是 "dead",但仍在通道上等待的匿名函数会发生什么情况?

它们会被当作垃圾收集起来,还是会永远徘徊在我的计算机内存的边缘地带(或者直到我杀死主线程)吞噬它,绝望地尝试在继续之前发送它们的最后一条消息?

你有 goroutine 泄漏。

package main

import (
    "fmt"
    "math/rand"
    "runtime"
    "strconv"
    "time"
)

func main() {
    for {
        text := foo()
        fmt.Println(text, "NumGoroutine", runtime.NumGoroutine())
        time.Sleep(time.Second)
    }
}

func foo() string {
    ch := make(chan string)
    for i := 0; i < 10; i++ {
        // Create some threads
        go func(i int) {
            time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
            ch <- strconv.Itoa(i)
        }(i)
    }
    return <-ch
}

输出:

$ go run leak.go
4 NumGoroutine 10
4 NumGoroutine 20
0 NumGoroutine 28
8 NumGoroutine 37
2 NumGoroutine 46
8 NumGoroutine 55
2 NumGoroutine 64
3 NumGoroutine 73
8 NumGoroutine 82
1 NumGoroutine 91
4 NumGoroutine 100
<<--SNIP-->>
4 NumGoroutine 4006
7 NumGoroutine 4015
6 NumGoroutine 4024
9 NumGoroutine 4033
9 NumGoroutine 4042
9 NumGoroutine 4051
1 NumGoroutine 4060
0 NumGoroutine 4069
4 NumGoroutine 4078
0 NumGoroutine 4087
6 NumGoroutine 4096
^Csignal: interrupt
$

像内存泄漏一样,goroutine 泄漏也很糟糕。

有关一些背景,请参阅 Go: proposal: runtime: garbage collect goroutines blocked forever #19702: Closed.