دروس الوحدة (2/5)
القنوات: الاتصال المكتوب
القنوات هي الآلية الاصطلاحية للتواصل بين الأشخاص goroutines. فلسفة الذهاب (روب بايك):
"لا تتواصل من خلال مشاركة الذاكرة، بل شارك الذاكرة من خلال التواصل."
القناة عبارة عن قائمة انتظار FIFO مكتوبة، وآمنة للنوع وآمنة للتزامن
استخدام. بالاشتراك مع go، فهو اللبنة الأساسية لـ 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بناء الجملة:
make(chan T)أوmake(chan T, N)للتخزين المؤقت.ch <- vيرسل.v := <-chيتلقى.v, ok := <-chيستقبل بعلامة (ok = falseإذا كانت القناة مغلقة وفارغة).
غير مخزن: موعد
كتل قناة غير مخزنة (سعة 0):
- المرسل حتى يصبح المستقبل جاهزًا؛
- المستلم حتى يصبح المرسل جاهزًا.
إنه موعد متزامن: مفيد كـ "إشارة" أو للضمان أن القيمة قد تم تسليمها.
مخزنة: قائمة الانتظار حتى N
ch := make(chan int, 3)
ch <- 1 // non blocca
ch <- 2 // non blocca
ch <- 3 // non blocca
ch <- 4 // BLOCCA: il buffer è pienoيقوم المرسل بالحظر فقط عندما يكون المخزن المؤقت ممتلئًا؛ المتلقي فقط عندما يكون فارغا.
قريب وللنطاق
يقوم المرسل بإغلاق القناة عند عدم وجود قيم أخرى:
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 على القناة يتكرر حتى يتم إغلاق القناة (وتصريفها).
إنه النمط الأنظف لـ "استهلك كل ما يصل".
الاتجاهية في التوقيعات
يمكن لمعلمات الوظيفة تقييد الاتجاه:
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 = إرسال فقط، <-chan T = استلام فقط. ثنائي الاتجاه
يمكن تمرير القناة chan T إلى أي منهما (التحويل الضمني). ذلك
يحسن الوضوح ويمنع الأخطاء.
الأنماط الشائعة (معاينة)
- مجموعة العمال: تستهلك goroutines N من
jobs <-chan T، وتنتج علىresults chan<- R. - خط الأنابيب: مراحل متصلة بالقنوات.
- إشارة الانتهاء: تم إغلاق قناة
chan struct{}للإشارة إلى "التوقف".
done := make(chan struct{})
go func() {
<-done // blocca finché qualcuno chiude done
cleanup()
}()
close(done) // segnale di stopchan struct{} هي قناة "الإشارة": صفر بايت من الحمولة، فقط
المزامنة.
جربه
قم بإنشاء قناة int غير مخزنة، وأرسل 42 من goroutine، واستقبلها بشكل رئيسي وقم بطباعتها.
إظهار التلميح
بدون مخزن مؤقت، تتم مزامنة المرسل والمستقبل.
الحل متاح بعد 3 من المحاولات
أرسل 1،2،3 عبر قناة مخزنة، وأغلقها، ثم اطبع كل شيء باستخدام النطاق.
إظهار التلميح
ينتهي "النطاق" فوق القناة عندما يتم إغلاق القناة وتصريفها.
الحل متاح بعد 3 من المحاولات
ماذا تفعل قناة UNBUFFERED عندما يرسل المرسل ولكن لا يوجد جهاز استقبال جاهز؟
ch := make(chan int)
ch <- 1 // ?خلاصة
- القناة = قائمة انتظار FIFO المكتوبة، آمنة بين goroutines.
- غير مخزن مؤقت: موعد (مزامنة المرسل والمستقبل).
- مخزنة: فصل، الكتل فقط عندما تكون ممتلئة/فارغة.
close(ch): المرسل فقط؛for rangeيستهلك حتى الإغلاق.- الاتجاهية:
chan<- T(إرسال فقط)،<-chan T(استقبال فقط). chan struct{}كقناة إشارة للمزامنة النقية.