Ana içeriğe geç
Modül 7 · Ders 2 ders 5Kurstaki 32/50~15 min
Modül dersleri (2/5)

Kanallar: yazılı iletişim

Kanallar arasında iletişim için kullanılan deyimsel mekanizmadır. gorutinler. Git felsefesi (Rob Pike):

"Hafızayı paylaşarak iletişim kurmayın; hafızayı iletişim kurarak paylaşın."

Kanal, tiplenmiş bir FIFO kuyruğu olup, tür açısından güvenlidir ve eş zamanlı kullanım için güvenlidir kullanın. go ile birleştiğinde Go'nun temel yapı taşıdır eşzamanlılık.

Oluşturun, gönderin, alın

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

Sözdizimi:

  • Arabelleğe alınmış için make(chan T) veya make(chan T, N).
  • ch <- v gönderir.
  • v := <-ch alır.
  • v, ok := <-ch bir bayrakla alır (ok = false eğer kanal kapalı VE boşsa).

Tamponlanmamış: randevu

Arabelleksiz bir kanal (kapasite 0) şunları engeller:

  • alıcı hazır olana kadar gönderen;
  • gönderen hazır olana kadar alıcı.

Bu eşzamanlı bir randevudur: bir "sinyal" olarak veya garanti olarak faydalıdır. değerin teslim edildiğini.

Arabelleğe alındı: N'ye kadar sıraya alı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

Gönderen yalnızca arabellek dolduğunda bloke eder; yalnızca alıcı boş olduğunda.

yakın ve uzak mesafe

Gönderen, daha fazla değer kalmadığında kanalı kapatır:

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)
}

Bir kanal üzerinden for range, kanal kapatılıncaya (ve boşalana kadar) yinelenir. "Gelen her şeyi tüket"in en temiz kalıbıdır.

İmzalarda yönlülük

Fonksiyon parametreleri yönü kısıtlayabilir:

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 = yalnızca gönderme, <-chan T = yalnızca alma. Çift yönlü chan T kanalı her ikisine de aktarılabilir (örtük dönüşüm). o netliği artırır ve hataları önler.

Ortak modeller (önizleme)

  • Çalışan havuzu: N goroutine jobs <-chan T'den tüketiyor, results chan<- R'de üretiyor.
  • Boru hattı: kanallarla birbirine bağlanan aşamalar.
  • Bitti sinyali: chan struct{} kanalı "dur" sinyali vermek üzere kapatıldı.
Go
done := make(chan struct{})
go func() {
    <-done    // blocca finché qualcuno chiude done
    cleanup()
}()
close(done)   // segnale di stop

chan struct{} "sinyal" kanalıdır: sıfır baytlık yük, sadece senkronizasyon.

Deneyin

Egzersiz#go.m7.l2.e1
Denemeler: 0Yükleniyor…

Arabelleksiz bir int kanal kanalı oluşturun, goroutine'den 42'yi gönderin, ana kanaldan alın ve yazdırın.

Düzenleyici yükleniyor…
İpucu göster

Tampon olmadan gönderen ve alıcı senkronize olur.

3 denemeden sonra çözüm mevcut

Egzersiz#go.m7.l2.e2
Denemeler: 0Yükleniyor…

Tamponlanmış bir kanal üzerinden 1,2,3'ü gönderin, kapatın ve ardından her şeyi for-range ile yazdırın.

Düzenleyici yükleniyor…
İpucu göster

Bir kanal üzerindeki "aralık için" işlevi, kanal kapatılıp boşaltıldığında sona erer.

3 denemeden sonra çözüm mevcut

Quiz#go.m7.l2.e3
Hazır

Gönderen gönderim yaptığında ancak alıcı hazır olmadığında, ARABELLEYMEYEN bir kanal ne yapar?

Go
ch := make(chan int)
ch <- 1 // ?
Cevap seçenekleri

Özet

  • Kanal = yazılı FIFO kuyruğu, goroutinler arasında güvenli.
  • Arabelleğe alınmamış: buluşma (gönderen ve alıcı senkronize edilir).
  • Ara belleğe alınmış: ayrıştırma, yalnızca dolu/boş olduğunda bloke eder.
  • close(ch): yalnızca gönderen; for range kapanışa kadar tüketir.
  • Yönsellik: chan<- T (yalnızca gönderme), <-chan T (yalnızca alma).
  • Saf senkronizasyon için bir sinyal kanalı olarak chan struct{}.