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
ch := make(chan int) // canale di int, unbuffered
go func() {
ch <- 42 // invia (può bloccare)
}()
v := <-ch // ricevi (può bloccare)
fmt.Println(v) // 42Sözdizimi:
- Arabelleğe alınmış için
make(chan T)veyamake(chan T, N). ch <- vgönderir.v := <-chalır.v, ok := <-chbir bayrakla alır (ok = falseeğ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
ch := make(chan int, 3)
ch <- 1 // non blocca
ch <- 2 // non blocca
ch <- 3 // non blocca
ch <- 4 // BLOCCA: il buffer è pienoGö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:
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:
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ı.
done := make(chan struct{})
go func() {
<-done // blocca finché qualcuno chiude done
cleanup()
}()
close(done) // segnale di stopchan struct{} "sinyal" kanalıdır: sıfır baytlık yük, sadece
senkronizasyon.
Deneyin
Arabelleksiz bir int kanal kanalı oluşturun, goroutine'den 42'yi gönderin, ana kanaldan alın ve yazdırın.
İpucu göster
Tampon olmadan gönderen ve alıcı senkronize olur.
3 denemeden sonra çözüm mevcut
Tamponlanmış bir kanal üzerinden 1,2,3'ü gönderin, kapatın ve ardından her şeyi for-range ile yazdırın.
İ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
Gönderen gönderim yaptığında ancak alıcı hazır olmadığında, ARABELLEYMEYEN bir kanal ne yapar?
ch := make(chan int)
ch <- 1 // ?Ö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 rangekapanış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{}.