可以打开频道吗?


160

如果我从未检查过Go通道的状态,可以永远保持打开状态(永远不关闭通道)可以吗?会导致内存泄漏吗?下列代码可以吗?

func (requestCh chan<- Request) GetResponse(data RequestData) Response {
    reply := make(chan Response)
    requestCh <- Request{data: data, replyCh: reply}
    return <-reply
}

Answers:


236

可以永远保持Go频道永远不关闭。当不再使用该通道时,将对其进行垃圾回收。

请注意,只有当接收器正在寻找关闭通道时,才需要关闭通道。关闭通道是通道上的控制信号,指示没有更多数据跟随。

设计问题:通道关闭


3
我不确定我是否同意该链接的回复。我的内存泄漏在2GB范围内。当我添加关闭时,间歇泉就成了a细流。
理查德

9
@Richard:仔细阅读整个线程。除非您正在寻找,否则Go gc的作者和gccgosay channel close的作者不是必需的close。那是权威建议。
peterSO

6
@peterSO,可能是,但是我知道我所看到的,那是我所报告的,所以请不要解雇我。
理查德

1
好吧,如果您有一个缓冲的通道,向其中添加消息应该使用内存。但是,如果您的频道未缓冲或未添加任何内容,则内存使用量将不会增加。
metakeule


31

是的,保持频道开放是可以的。正如go编程语言书所述:

完成所有频道后,您无需关闭每个频道。仅当必须告知接收goroutines已发送所有数据时,才需要关闭通道。垃圾回收器确定其无法访问的通道将回收其资源,无论该通道是否关闭。(不要将它与打开文件的关闭操作混淆。在完成每个文件后调用Close方法很重要 。)


7

是的,可以将通道保持打开状态,这实际上是很典型的。打开的通道不会构成对通道对象的引用,因此不会阻止对其进行垃圾回收。


1

使用Go通道的一个普遍原则是,不要从接收方关闭通道,如果通道有多个并发发送者,则不要关闭通道。

正如上面的答案中明确提到的,每个通道一旦标记为要清理就将最终被GC,因此可以不关闭通道而已,唯一的区别是该通道将gc在几个周期后可用没有明确关闭。

还下面的文章这个这个节目各种方式中的1例关闭通道:N,N:1或M:N(发件人:接收器)


-5

Go是垃圾收集的,因此您实际上不必“释放”任何东西。

可以关闭通道,但它通常用作-close(channel)-告诉goroutine(或主程序)该通道上将不会发送任何其他消息。


8
AFAIK甚至使用垃圾收集语言,程序员仍然负责释放非托管资源,例如关闭文件,套接字等。我需要像文件一样关闭频道吗?
克鲁伊2011年

3
@Kluyg答案是否定的。您正在谈论OS资源(哪些渠道不是)。它取决于资源和语言,但是通常建议手动关闭OS资源,不是因为GC不会这样做,而是因为它不确定。最常见的相关陷阱打开文件过多错误。您一直在打开文件...您希望GC能够这样做...您不会用完内存(因此GC也不会启动)...您在OS级别上已用完文件描述符。OS杀死了进程:)
Pijusn

我感到困惑的是,为什么它在整个过程中都是正确的,却得到了如此之多的票数,并与其他公认的答案一样?……
eja
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.