Czy mogę zostawić otwarty kanał?

160

Czy mogę zostawić kanał Go otwarty na zawsze (nigdy nie zamykać kanału), jeśli nigdy nie sprawdzę jego stanu? Czy doprowadzi to do wycieków pamięci? Czy poniższy kod jest prawidłowy?

func (requestCh chan<- Request) GetResponse(data RequestData) Response {
    reply := make(chan Response)
    requestCh <- Request{data: data, replyCh: reply}
    return <-reply
}
Kluyg
źródło

Odpowiedzi:

236

Możesz zostawić kanał Go otwarty na zawsze i nigdy go nie zamykać. Gdy kanał nie jest już używany, zostanie usunięty.

Należy pamiętać, że zamknięcie kanału jest konieczne tylko wtedy, gdy odbiornik szuka zamknięcia. Zamknięcie kanału jest sygnałem sterującym na kanale wskazującym, że nie następuje już więcej danych.

Pytanie projektowe: zamknięcie kanału

peterSO
źródło
3
Nie jestem pewien, czy zgadzam się z odpowiedzią na link. Miałem wyciek pamięci w zakresie 2 GB. Jak tylko dodałem blisko, gejzer zamienił się w strużkę.
Richard
9
@Richard: Przeczytaj uważnie cały wątek. Autor Go gci autor gccgopowiedzmy kanałów closenie są potrzebni, chyba że szukasz pliku close. To miarodajna rada.
peterSO
6
@peterSO, to może być, ale wiem, co widziałem i to właśnie zgłosiłem, więc proszę mnie nie odrzucać.
Richard
1
Cóż, jeśli masz kanał buforowany, dodawanie do niego wiadomości powinno wykorzystywać pamięć. Jeśli jednak Twój kanał nie jest buforowany lub nic nie zostanie dodane, użycie pamięci nie wzrośnie.
metakeule
31

Tak, otwarcie kanału jest w porządku. Jak stwierdzono w książce o języku programowania go :

Po zakończeniu nie musisz zamykać każdego kanału. Zamknięcie kanału jest konieczne tylko wtedy, gdy ważne jest, aby poinformować gorutynę odbierającą, że wszystkie dane zostały wysłane. Kanał, który moduł odśmiecania określi jako nieosiągalny, będzie miał odzyskane zasoby niezależnie od tego, czy jest zamknięty. (Nie myl tego z operacją close dla otwartych plików. Ważne jest, aby wywołać metodę Close na każdym pliku, kiedy skończysz.)

cizixs
źródło
7

Tak, pozostawienie otwartego kanału jest w porządku i jest to typowe. Otwarty kanał nie stanowi odwołania do obiektu kanału, a więc nie chroni go przed wyrzucaniem elementów bezużytecznych.

Sonia
źródło
1

Ogólna zasada korzystania z kanałów Go polega na tym, że nie zamykaj kanału od strony odbiornika i nie zamykaj kanału, jeśli kanał ma wielu współbieżnych nadawców. ”.

Jak wyraźnie wspomniano w powyższej odpowiedzi, każdy kanał zostanie ostatecznie poddany GC, gdy zostanie oznaczony do czyszczenia, więc można pozostawić kanał niezamknięty, jedyną różnicą, jaką spowoduje, jest to, że kanał ten będzie dostępny dla gc po kilku cyklach, jeśli nie zamknięte jawnie.

Również poniższe artykuły to i to pokazują różne sposoby zamykania kanału w przypadku 1: N, N: 1 lub M: N (nadawcy: odbiorcy)

Abhishek Srivastava
źródło
-5

Go jest zbierane jako śmieci, więc tak naprawdę nie musisz niczego „uwalniać”.

Istnieje możliwość zamknięcia kanałów, ale najczęściej jest to używane jako - zamknij (kanał) - mówi goroutine (lub programowi głównemu), że nic więcej nie zostanie wysłane na tym kanale.

Łukasz Gruner
źródło
8
AFAIK nawet w języku zbierania śmieci programista jest nadal odpowiedzialny za zwolnienie niezarządzanych zasobów, np. Zamykanie plików, gniazd i tak dalej. Czy muszę zamykać kanał jak plik?
Kluyg
3
@Kluyg Odpowiedź brzmi: nie. Mówisz o zasobach systemu operacyjnego (które kanały nie są). Zależy to od zasobu i języka, ale zwykle zaleca się ręczne zamykanie zasobów systemu operacyjnego nie dlatego, że GC by tego nie zrobił, ale raczej dlatego, że jest niedeterministyczny. Najczęstszym związane haczyka jest zbyt wiele otwartych plików błędu. Ciągle otwierasz pliki ... Spodziewasz się, że GC to zrobi ... Nie zabraknie Ci pamięci (dlatego GC nie uruchamia się) ... Skończyły Ci się deskryptory plików na poziomie systemu operacyjnego. System operacyjny zabija proces :)
Pijusn,
Jestem zdezorientowany, dlaczego otrzymałem tak wiele głosów przeciw, podczas gdy przez cały czas było poprawne i stanowi to samo, co inne zaakceptowane odpowiedzi ...
eja