Pelajaran modul (2/5)
Saluran: komunikasi yang diketik
Saluran adalah mekanisme idiomatis untuk komunikasi antar goroutine. Filosofi Go (Rob Pike):
"Jangan berkomunikasi dengan berbagi memori; berbagi memori dengan berkomunikasi."
Saluran adalah antrean FIFO yang diketik, aman untuk tipe dan aman untuk digunakan secara bersamaan
gunakan. Dikombinasikan dengan go, ini adalah elemen penyusun utama Go
konkurensi.
Buat, kirim, terima
ch := make(chan int) // canale di int, unbuffered
go func() {
ch <- 42 // invia (può bloccare)
}()
v := <-ch // ricevi (può bloccare)
fmt.Println(v) // 42Sintaksis:
make(chan T)ataumake(chan T, N)untuk buffering.ch <- vterkirim.v := <-chmenerima.v, ok := <-chmenerima dengan bendera (ok = falsejika saluran ditutup DAN kosong).
Tanpa buffer: pertemuan
Saluran tanpa buffer (kapasitas 0) diblokir:
- pengirim hingga penerima siap;
- penerima hingga pengirim siap.
Ini adalah janji yang sinkron: berguna sebagai "sinyal" atau sebagai jaminan bahwa nilainya telah diserahkan.
Buffer: mengantri hingga N
ch := make(chan int, 3)
ch <- 1 // non blocca
ch <- 2 // non blocca
ch <- 3 // non blocca
ch <- 4 // BLOCCA: il buffer è pienoPengirim hanya memblokir ketika buffer penuh; penerimanya saja ketika kosong.
jarak dekat dan jarak jauh
Pengirim menutup saluran ketika tidak ada lagi nilai:
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
for v := range ch { // termina quando ch è chiuso E vuoto
fmt.Println(v)
}for range melalui saluran diulang hingga saluran ditutup (dan dikosongkan).
Ini adalah pola paling bersih untuk "mengkonsumsi segala sesuatu yang datang".
Arah dalam tanda tangan
Parameter fungsi dapat membatasi arah:
func producer(out chan<- int) { // solo invio
out <- 1
close(out)
}
func consumer(in <-chan int) { // solo ricezione
for v := range in {
fmt.Println(v)
}
}chan<- T = hanya kirim, <-chan T = hanya menerima. Dua arah
saluran chan T dapat diteruskan ke salah satu (konversi implisit). Itu
meningkatkan kejelasan dan mencegah kesalahan.
Pola umum (pratinjau)
- Kelompok pekerja: N goroutine dikonsumsi dari
jobs <-chan T, diproduksi diresults chan<- R. - Pipeline: tahapan yang dihubungkan oleh saluran.
- Sinyal selesai: saluran
chan struct{}ditutup untuk memberi sinyal "berhenti".
done := make(chan struct{})
go func() {
<-done // blocca finché qualcuno chiude done
cleanup()
}()
close(done) // segnale di stopchan struct{} adalah saluran "sinyal": muatan nol byte, cukup
sinkronisasi.
Cobalah
Buat ch saluran int tanpa buffer, kirim 42 dari goroutine, terima di main dan cetak.
Tunjukkan petunjuk
Tanpa buffer, pengirim dan penerima melakukan sinkronisasi.
Solusi tersedia setelah 3 upaya
Kirim 1,2,3 melalui saluran buffered, tutup, lalu cetak semuanya dengan for-range.
Tunjukkan petunjuk
`untuk rentang` pada saluran berakhir ketika saluran ditutup dan dikosongkan.
Solusi tersedia setelah 3 upaya
Apa yang dilakukan saluran UNBUFFERED ketika pengirim mengirim tetapi tidak ada penerima yang siap?
ch := make(chan int)
ch <- 1 // ?Rekap
- Channel = antrian FIFO yang diketik, aman antar goroutine.
- Unbuffered: rendezvous (sinkronisasi pengirim dan penerima).
- Buffer: decoupling, blok hanya ketika penuh/kosong.
close(ch): hanya pengirimnya;for rangedikonsumsi hingga hampir habis.- Arah:
chan<- T(hanya kirim),<-chan T(hanya terima). chan struct{}sebagai saluran sinyal untuk sinkronisasi murni.