الانتقال إلى المحتوى الرئيسي
الوحدة 7 · الدرس 2 من 532/50 في الدورة~15 min
دروس الوحدة (2/5)

القنوات: الاتصال المكتوب

القنوات هي الآلية الاصطلاحية للتواصل بين الأشخاص goroutines. فلسفة الذهاب (روب بايك):

"لا تتواصل من خلال مشاركة الذاكرة، بل شارك الذاكرة من خلال التواصل."

القناة عبارة عن قائمة انتظار FIFO مكتوبة، وآمنة للنوع وآمنة للتزامن استخدام. بالاشتراك مع go، فهو اللبنة الأساسية لـ 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

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

يقوم المرسل بالحظر فقط عندما يكون المخزن المؤقت ممتلئًا؛ المتلقي فقط عندما يكون فارغا.

قريب وللنطاق

يقوم المرسل بإغلاق القناة عند عدم وجود قيم أخرى:

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 على القناة يتكرر حتى يتم إغلاق القناة (وتصريفها). إنه النمط الأنظف لـ "استهلك كل ما يصل".

الاتجاهية في التوقيعات

يمكن لمعلمات الوظيفة تقييد الاتجاه:

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 = إرسال فقط، <-chan T = استلام فقط. ثنائي الاتجاه يمكن تمرير القناة chan T إلى أي منهما (التحويل الضمني). ذلك يحسن الوضوح ويمنع الأخطاء.

الأنماط الشائعة (معاينة)

  • مجموعة العمال: تستهلك goroutines N من jobs <-chan T، وتنتج على results chan<- R.
  • خط الأنابيب: مراحل متصلة بالقنوات.
  • إشارة الانتهاء: تم إغلاق قناة chan struct{} للإشارة إلى "التوقف".
Go
done := make(chan struct{})
go func() {
    <-done    // blocca finché qualcuno chiude done
    cleanup()
}()
close(done)   // segnale di stop

chan struct{} هي قناة "الإشارة": صفر بايت من الحمولة، فقط المزامنة.

جربه

تمرين#go.m7.l2.e1
المحاولات: 0جارٍ التحميل…

قم بإنشاء قناة int غير مخزنة، وأرسل 42 من goroutine، واستقبلها بشكل رئيسي وقم بطباعتها.

جارٍ تحميل المحرر…
إظهار التلميح

بدون مخزن مؤقت، تتم مزامنة المرسل والمستقبل.

الحل متاح بعد 3 من المحاولات

تمرين#go.m7.l2.e2
المحاولات: 0جارٍ التحميل…

أرسل 1،2،3 عبر قناة مخزنة، وأغلقها، ثم اطبع كل شيء باستخدام النطاق.

جارٍ تحميل المحرر…
إظهار التلميح

ينتهي "النطاق" فوق القناة عندما يتم إغلاق القناة وتصريفها.

الحل متاح بعد 3 من المحاولات

Quiz#go.m7.l2.e3
جاهز

ماذا تفعل قناة UNBUFFERED عندما يرسل المرسل ولكن لا يوجد جهاز استقبال جاهز؟

Go
ch := make(chan int)
ch <- 1 // ?
خيارات الإجابة

خلاصة

  • القناة = قائمة انتظار FIFO المكتوبة، آمنة بين goroutines.
  • غير مخزن مؤقت: موعد (مزامنة المرسل والمستقبل).
  • مخزنة: فصل، الكتل فقط عندما تكون ممتلئة/فارغة.
  • close(ch): المرسل فقط؛ for range يستهلك حتى الإغلاق.
  • الاتجاهية: chan<- T (إرسال فقط)، <-chan T (استقبال فقط).
  • chan struct{} كقناة إشارة للمزامنة النقية.