Чи добре залишити канал відкритим?


160

Чи добре залишити канал Go відкритим назавжди (ніколи не закривати канал), якщо я ніколи не перевіряю його стан? Чи призведе це до витоку пам'яті? Чи в порядку наступний код?

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

Відповіді:


236

Добре залишати канал Go відкритим назавжди і ніколи не закривати його. Коли канал більше не використовується, він буде збирати сміття.

Зауважте, що закривати канал потрібно лише тоді, коли приймач шукає закриття. Закриття каналу - це керуючий сигнал на каналі, який вказує, що більше даних не випливає.

Питання дизайну: Закриття каналу


3
Я не впевнений, що згоден з відповіддю на посилання. У мене витік пам'яті в діапазоні 2 Гб. Як тільки я додав закриття, гейзер став дрібницею.
Річард

9
@Richard: Уважно прочитайте всю нитку. Автор Go gcта автор gccgoкажуть, що канал closes не потрібен, якщо ви не шукаєте close. Це авторитетна порада.
peterSO

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

1
Добре, якщо у вас є захищений канал, для додавання до нього повідомлень слід використовувати пам'ять. Однак якщо ваш канал не буферний або нічого не додано, використання пам'яті не зростатиме.
metakeule


31

Так, нормально тримати канал відкритим. Як зазначено у книзі мови програмування «go» :

Вам не потрібно закривати кожен канал, коли ви закінчили його. Закрити канал потрібно лише тоді, коли важливо повідомити приймаючим програмам, що всі дані були надіслані. На каналі, який сміттєзбірник визначає недоступним, його ресурси будуть відкликані, закритий він чи ні. (Не плутайте це з операцією закриття для відкритих файлів. Важливо викликати метод закриття на кожному файлі, коли ви закінчили його.)


7

Так, нормально залишати канал відкритим, і насправді це типово. Відкритий канал не є посиланням на об’єкт каналу, і тому не перешкоджає його збору сміття.


1

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

Як було чітко зазначено у відповіді вище, що кожен канал буде зрештою GCed після того, як він буде позначений для очищення, тож добре залишити канал незакритим. Єдина різниця, яку це зробить - це те, що цей канал буде доступний gcчерез кілька циклів, можливо, якщо не закрито явно.

Також у наступних статтях це та це показує різні способи закриття каналу у випадку 1: N, N: 1 або M: N (відправники: приймачі)


-5

Go збирається сміття, тому вам не потрібно нічого "звільняти".

Існує можливість закрити канали, але в основному використовується як - close (канал) - скажіть gorouttu (або основній програмі), що більше нічого не буде надсилатися на цей канал.


8
AFAIK навіть на мові, зібраній зі сміттям, програміст все ще відповідає за звільнення некерованих ресурсів, наприклад, закриття файлів, сокетів тощо. Чи потрібно закривати канал, як файл?
Клюйг

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

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