Historia pytania:
Kanały (chan) - kluczowe narzędzie do wymiany danych między gorutynami i synchronizacji procesów współbieżnych, co jednoznacznie wyróżnia Go spośród innych języków. Są przeznaczone do organizacji bezpiecznego przesyłania danych.
Problem:
Bez właściwego zrozumienia budowy kanałów deweloperzy często napotykają na deadlocki, nieoczekiwane zablokowania, nieoczywiste błędy przy zamykaniu kanału oraz utratę danych (race condition).
Rozwiązanie:
Należy dokładnie rozumieć jak ogłaszać, używać, zamykać kanały. Decydować, kiedy używać kanałów buforowanych/niebuforowanych i monitorować, kto i kiedy powinien zamknąć kanał, aby uniknąć "wszystko zacięte".
Przykład kodu:
func producent(ch chan<- int) { // tylko wysyłanie for i := 0; i < 5; i++ { ch <- i } close(ch) } func konsument(ch <-chan int) { // tylko odczyt for v := range ch { fmt.Println(v) } } func main() { ch := make(chan int) go producent(ch) konsument(ch) }
Kluczowe cechy:
Co się stanie, gdy spróbujesz zapisać do zamkniętego kanału?
Pojawi się panic. Często spotykanym błędem jest zamykanie kanału po stronie czytelnika lub pozwalanie na zapis do kanału po jego zamknięciu.
Czy można bezpiecznie sprawdzić, czy kanał jest zamknięty?
Nie, nie ma bezpośredniego sprawdzenia. Trzeba tylko właściwie projektować kontrolę nad życiem kanału lub używać drugiego parametru podczas odczytu (v, ok := <-ch), który stanie się false, gdy kanał jest zamknięty.
Czy kanał jest bezpieczny wątkowo sam w sobie?
Kanał - jest bezpieczny wątkowo do przesyłania danych między gorutynami. Ale jeśli kilka gorutyn zapisuje do jednego kanału, bez koordynacji może to prowadzić do problemów (możliwe przedwczesne zamknięcie).
Projekt z wieloma producentami i jednym konsumentem: kanał był zamykany przez każdego producenta, w rezultacie - panic w czasie wykonywania przy próbie podwójnego zamknięcia, dane były tracone.
Zalety:
Wady:
Użyto tylko jeden wątek do zamknięcia kanału, a producenci przez osobną WaitGroup sygnalizowali zakończenie pracy. Kanał służył wyłącznie do przesyłania wyników.
Zalety:
Wady: