Можно ли оставить канал открытым?


161

Можно ли оставлять канал Go открытым всегда (никогда не закрывать канал), если я никогда не проверю его состояние? Приведет ли это к утечкам памяти? Следующий код в порядке?

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

Ответы:


238

Можно оставить канал Go открытым навсегда и никогда не закрывать его. Когда канал больше не используется, он будет собирать мусор.

Обратите внимание, что необходимо только закрыть канал, если приемник ищет закрытие. Закрытие канала является управляющим сигналом на канале, указывающим, что больше нет данных.

Вопрос о дизайне: закрытие канала


3
Я не уверен, что согласен с ответом по ссылке. У меня была утечка памяти в диапазоне 2 ГБ. Как только я добавил закрытие, гейзер стал струйкой.
Ричард

9
@Richard: внимательно прочитайте всю ветку. Автор Go gcи автор, gccgoскажем, канала closes не нужны, если вы не ищете a close. Это авторитетный совет.
peterSO

6
@peterSO, это может быть, но я знаю, что я видел, и это то, что я сообщил, поэтому, пожалуйста, не увольняйте меня.
Ричард

1
Хорошо, если у вас есть буферизованный канал, добавление сообщений на него должно использовать память. Однако, если ваш канал не буферизован или ничего не добавлено, использование памяти не будет расти.
metakeule


31

Да, нормально держать канал открытым. Как написано в книге по языку программирования go :

Вам не нужно закрывать каждый канал, когда вы закончили с ним. Необходимо только закрыть канал, когда важно сообщить принимающим процедурам, что все данные были отправлены. Канал, который сборщик мусора определит как недоступный, восстановит свои ресурсы независимо от того, закрыт он или нет. (Не путайте это с операцией close для открытых файлов. Важно вызывать метод Close для каждого файла, когда вы закончите с ним.)


7

Да, нормально оставлять канал открытым, и на самом деле это типично. Открываемый канал не является ссылкой на объект канала и не препятствует его сборке.


1

« Один общий принцип использования каналов Go - не закрывать канал со стороны получателя и не закрывать канал, если канал имеет несколько одновременных отправителей ».

Как ясно сказано в ответе выше, каждый канал будет в конечном итоге GCed после того, как он будет помечен для очистки, поэтому можно оставить канал закрытым, единственное отличие, которое он будет иметь, состоит в том, что этот канал будет доступен gcпосле нескольких циклов, возможно, если не закрыт явно

Также в следующих статьях это и это показывают различные способы закрытия канала в случае 1: N, N: 1 или M: N (отправители: получатели)


-5

Go - это сборщик мусора, поэтому вам не нужно ничего «освобождать».

Существует возможность закрытия каналов, но в основном она используется как - close (channel) - сообщает goroutine (или основной программе), что на этом канале больше ничего не будет отправлено.


8
AFAIK, даже на языке, предназначенном для сбора мусора, программист по-прежнему отвечает за освобождение неуправляемых ресурсов, например, закрытие файлов, сокетов и так далее. Нужно ли закрывать канал как файл?
Клюйг

3
@Kluyg Ответ - нет. Вы говорите о ресурсах ОС (каких каналов нет). Это зависит от ресурса и языка, но обычно рекомендуется закрывать ресурсы ОС вручную не потому, что GC этого не сделает, а потому, что он недетерминирован. Наиболее часто связанные Гоча является слишком много открытых файлов ошибок. Вы продолжаете открывать файлы ... Вы ожидаете, что GC сделает это ... У вас не хватает памяти (поэтому GC не запускается) ... У вас заканчиваются файловые дескрипторы на уровне ОС. ОС убивает процесс :)
Pijusn

Я не понимаю, почему так много отрицательных отзывов, в то время как это было правильно все время и говорит так же, как и другие принятые ответы ...
eja
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.