Lompati ke konten utama
Modul 7 · Pelajaran 2 dari 532/50 dalam kursus~15 min
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

Go
ch := make(chan int)     // canale di int, unbuffered

go func() {
    ch <- 42             // invia (può bloccare)
}()

v := <-ch                // ricevi (può bloccare)
fmt.Println(v)           // 42

Sintaksis:

  • make(chan T) atau make(chan T, N) untuk buffering.
  • ch <- v terkirim.
  • v := <-ch menerima.
  • v, ok := <-ch menerima dengan bendera (ok = false jika 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

Go
ch := make(chan int, 3)
ch <- 1   // non blocca
ch <- 2   // non blocca
ch <- 3   // non blocca
ch <- 4   // BLOCCA: il buffer è pieno

Pengirim hanya memblokir ketika buffer penuh; penerimanya saja ketika kosong.

jarak dekat dan jarak jauh

Pengirim menutup saluran ketika tidak ada lagi nilai:

Go
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:

Go
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 di results chan<- R.
  • Pipeline: tahapan yang dihubungkan oleh saluran.
  • Sinyal selesai: saluran chan struct{} ditutup untuk memberi sinyal "berhenti".
Go
done := make(chan struct{})
go func() {
    <-done    // blocca finché qualcuno chiude done
    cleanup()
}()
close(done)   // segnale di stop

chan struct{} adalah saluran "sinyal": muatan nol byte, cukup sinkronisasi.

Cobalah

Latihan#go.m7.l2.e1
Upaya: 0Memuat…

Buat ch saluran int tanpa buffer, kirim 42 dari goroutine, terima di main dan cetak.

Memuat editor…
Tunjukkan petunjuk

Tanpa buffer, pengirim dan penerima melakukan sinkronisasi.

Solusi tersedia setelah 3 upaya

Latihan#go.m7.l2.e2
Upaya: 0Memuat…

Kirim 1,2,3 melalui saluran buffered, tutup, lalu cetak semuanya dengan for-range.

Memuat editor…
Tunjukkan petunjuk

`untuk rentang` pada saluran berakhir ketika saluran ditutup dan dikosongkan.

Solusi tersedia setelah 3 upaya

Quiz#go.m7.l2.e3
Siap

Apa yang dilakukan saluran UNBUFFERED ketika pengirim mengirim tetapi tidak ada penerima yang siap?

Go
ch := make(chan int)
ch <- 1 // ?
Pilihan jawaban

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 range dikonsumsi hingga hampir habis.
  • Arah: chan<- T (hanya kirim), <-chan T (hanya terima).
  • chan struct{} sebagai saluran sinyal untuk sinkronisasi murni.