9

Consider the following code as a simplified example:

func printer(c <-chan int) {
    for {
        fmt.Print(<-c)
    }
}

func provide() {
    c := make(chan int)

    go printer(c)

    for i := 1; i <= 100; i++ {
        c <- i
    }
}

The function provide creates a go routine printer that prints the data provide generates.

My question is, what happens after provide returns and printer starts blocking on the empty channel. Will the go routine leak, as there is no further reference to c or will the garbage collector catch this case and dispose both the go routine and c?

If it is indeed the case that this kind of code causes a memory leak, what strategies can I do to prevent such a memory leak from happening?

4

2 回答 2

10

关闭频道。从关闭的通道读取始终成功,并返回相应的零值。可选的第二个布尔返回值指示第一个值的有效性。

接收运营商

在表单的赋值或初始化中使用的接收表达式

x, ok = <-ch
x, ok := <-ch
var x, ok = <-ch

产生一个额外的结果类型bool报告通信是否成功。如果接收到的值ok是通过成功的发送操作传递到通道的,则值为 true,如果它是由于通道关闭且为空而生成的零值,则值为 false。

func printer(c <-chan int) {
        for {
                v, ok := <-c
                if !ok { // chan closed
                        return
                }

                // v is valid
                fmt.Println(v)
        }
}

func provide() {
        c := make(chan int)

        go printer(c)

        for i := 1; i <= 100; i++ {
                c <- i
        }
        close(c)
}
于 2013-05-16T15:37:12.113 回答
0

尝试以下程序来验证这确实会泄漏内存。请注意,该程序会很快耗尽您的 RAM;准备杀死它。

package main

func worker(c <-chan int) {
    var i int

    for {
        i += <-c
    }
}

func wrapper() {
    c := make(chan int)

    go worker(c)

    for i := 0; i < 0xff; i++ {
        c <- i
    }
}

func main() {
    for {
        wrapper()
    }
}

为了解决泄漏,请关闭现在孤立的 go 例程引用的通道。运行时会注意到仅从关闭的通道读取的 Go 例程将永远不会继续并继续释放它。固定代码如下所示:

package main

func worker(c <-chan int) {
    var i int

    for {
        i += <-c
    }
}

func wrapper() {
    c := make(chan int)
    defer close(c) // fix here

    go worker(c)

    for i := 0; i < 0xff; i++ {
        c <- i
    }
}

func main() {
    for {
        wrapper()
    }
}
于 2013-05-16T15:22:04.193 回答