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

时间:2017-04-19 11:03:13

标签: go lambda lifecycle channel

我有一个函数创建一个没有缓冲区的通道。该函数继续创建写入所述通道的若干其他并发匿名函数。然后该函数继续等待通道上的输入,然后返回该值。

见下面的例子

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)“死”,仍在等待通道的匿名函数会发生什么?

他们会被收集为垃圾,还是他们会永远徘徊在我的计算机内存的边缘(或者直到我杀死主线程)吃掉它,在绝望的尝试中传递他们的最后一条消息然后传递?

1 个答案:

答案 0 :(得分:2)

你有一个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.