W Go kanał to środek do przesyłania danych między gorutynami z synchronizacją. Rozróżniamy:
Używanie kanałów niebuforowanych jest wygodne tam, gdzie synchronizacja jest krytyczna i trzeba zagwarantować, że nadawca i odbiorca spotkali się w tym samym miejscu w kodzie. Buforowane nadają się do przesyłania danych "z zapasem" — do organizacji kolejek, pracowników, zadań asynchronicznych.
func main() { ch := make(chan int) // niebuforowany go func() { ch <- 42 // blokuje się, dopóki nie ma odbiornika }() fmt.Println(<-ch) bufch := make(chan int, 2) // buforowany na 2 elementy bufch <- 1 // nie blokuje się bufch <- 2 // nie blokuje się // następne wysłanie zablokuje, jeśli nie będzie odczytu }
Czy kanał buforowany może służyć jako zamiennik kolejki między dziesiątkami producentów i konsumentów bez dodatkowej synchronizacji?
Często odpowiada się — "tak". W rzeczywistości, tylko jeśli nie jest ważna gwarancja kolejności i wiadomości nie są tracone. Przy kilku czytelnikach/pisarzach mogą wystąpić sytuacje wyścigów i utraty danych, dlatego kontrola synchronizacji jest nadal potrzebna (worker pool, mutexy, konteksty do zamykania kanałów).
Historia
W przetwarzaniu logów programiści używali kanału buforowanego o długości 1000 do przesyłania zdarzeń między parserem a agregatorem. Przy zatrzymaniu usługi zapomnieli zamknąć kanał, a część wydarzeń "zgubiła się" — pracownicy zakończyli przed przetworzeniem całego bufora. Zostało to naprawione przez jawne zamknięcie kanałów i blokadę do pełnego wyładowania.
Historia
Przy próbie zastąpienia kolejki mutex na kanał buforowany w rozproszonym serwisie nie uwzględniono sytuacji "zawieszonych" nadawców: przy pełnym buforze blokada wysyłania w końcu spowolniła cały system, doprowadziła do przekroczenia czasu, a interfejs zaczął "lagować". Po analizie przywrócono część synchronizacji z powrotem za pomocą zmiennych warunkowych.
Historia
W module telemetrii używano niebuforowanego kanału do logowania błędów między modułem a konsumentem. Z powodu przypadkowego opóźnienia przetwarzania pisak blokował się, a w ciągu minuty zebrano kolejkę z setek tysięcy danych w gorutynach — wystąpił "out of goroutines". Naprawiono to, zastępując kanał niebuforowany kanałem buforowanym oraz asynchronicznym pracownikiem do oczyszczania kolejki.