0Pricing
Go Academy · درس

القنوات غير المخزَّنة

تسليم متزامن بين Goroutines

القنوات غير المخزَّنة درس مجاني في Go Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Go Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Go Academy 4 دروس في المجموع.

ما هي القناة؟

القناة channel هي وسيلة اتصال ذات نوع محدد بين الغوروتينات. وتتبع القنوات مبدأ Go: لا تتواصلوا عبر مشاركة الذاكرة؛ شاركوا الذاكرة عبر التواصل.

package main
import "fmt"

func main() {
    ch := make(chan int)   // unbuffered int channel

    go func() {
        ch <- 42  // send: blocks until someone receives
    }()

    v := <-ch  // receive: blocks until someone sends
    fmt.Println(v) // 42
}

دلالات القناة غير المخزنة مؤقتًا

لا تملك القناة غير المخزنة مؤقتًا أي سعة. يُحظر الإرسال حتى يصبح مستقبل جاهزًا، ويُحظر الاستقبال حتى يرسل أحدهم. وهذا يضمن تسليمًا متزامنًا:

package main
import "fmt"

func double(in <-chan int, out chan<- int) {
    for v := range in {
        out <- v * 2
    }
    close(out)
}

func main() {
    in := make(chan int)
    out := make(chan int)
    go double(in, out)
    go func() { in <- 3; in <- 5; close(in) }()
    for v := range out { fmt.Println(v) }
    // 6
    // 10
}

القناة بوصفها أداة للمزامنة

تزامن القنوات غير المخزنة مؤقتًا بين الغوروتينات — استخدموها كإشارة إلى اكتمال العمل:

package main
import "fmt"

func compute(result chan<- int) {
    sum := 0
    for i := 1; i <= 100; i++ { sum += i }
    result <- sum
}

func main() {
    ch := make(chan int)
    go compute(ch)
    fmt.Println("Result:", <-ch) // blocks until compute sends
}

إغلاق قناة

يغلق المرسل القناة باستخدام close(ch) للإشارة إلى أنه لن تُرسل قيم أخرى. ويكتشف المستقبلون الإغلاق باستخدام الصيغة ذات القيمتين:

package main
import "fmt"

func generate(ch chan<- int, max int) {
    for i := 0; i < max; i++ {
        ch <- i
    }
    close(ch)  // signal done
}

func main() {
    ch := make(chan int)
    go generate(ch, 5)

    for v := range ch {  // range detects close automatically
        fmt.Println(v)
    }
    fmt.Println("channel closed")
}

الاستقبال بقيمتين

يُخبركم الاستقبال بقيمتين v, ok := <-ch بما إذا كانت القناة لا تزال مفتوحة:

package main
import "fmt"

func main() {
    ch := make(chan string, 1)
    ch <- "hello"
    close(ch)

    v1, ok1 := <-ch
    fmt.Println(v1, ok1)  // hello true

    v2, ok2 := <-ch
    fmt.Println(v2, ok2)  // "" false — channel closed
}

الإرسال إلى قناة مغلقة يسبب panic

يؤدي الإرسال إلى قناة مغلقة إلى حدوث panic. يجب أن يغلق المرسل القناة فقط — ولا يغلقها المستقبل مطلقًا:

package main
import "fmt"

func main() {
    ch := make(chan int)
    close(ch)

    // Receiving from closed channel returns zero value
    v, ok := <-ch
    fmt.Println(v, ok)  // 0 false

    // Sending to closed channel panics:
    defer func() { recover() }()
    ch <- 1  // panic: send on closed channel
}

القنوات أحادية الاتجاه

قيّدوا القنوات لتكون للإرسال فقط (chan<- T) أو للاستقبال فقط (<-chan T) في تواقيع الدوال، من أجل الوضوح والأمان:

package main
import "fmt"

func producer(out chan<- int) {  // send-only
    for i := 0; i < 3; i++ { out <- i }
    close(out)
}

func consumer(in <-chan int) {   // receive-only
    for v := range in { fmt.Println(v) }
}

func main() {
    ch := make(chan int)
    go producer(ch)
    consumer(ch)
}

تبادل الرسائل بين الغوروتينات والقنوات

تتبادل غوروتينتان رسالة ذهابًا وإيابًا عبر القنوات — وهو مثال كلاسيكي على المزامنة:

package main
import "fmt"

func ping(ping, pong chan struct{}) {
    for i := 0; i < 3; i++ {
        <-ping
        fmt.Println("ping")
        pong <- struct{}{}
    }
}

func main() {
    ping := make(chan struct{})
    pong := make(chan struct{})
    go func() { for { <-pong; fmt.Println("pong"); ping <- struct{}{} } }()
    go func() { for i := 0; i < 3; i++ { ping <- struct{}{}; <-pong } }()
    // Simplified version:
    fmt.Println("channels enable structured communication")
}

القنوات nil تُحظر إلى الأبد

يُحظر الاستقبال من قناة nil أو الإرسال إليها إلى الأبد. ويُستخدم ذلك أحيانًا عن قصد في عبارات select:

package main
import "fmt"

func main() {
    var ch chan int  // nil channel
    fmt.Println(ch == nil) // true

    // select with nil channel — that case is never selected
    active := make(chan int, 1)
    active <- 42
    select {
    case v := <-ch:      // never selected (nil)
        fmt.Println(v)
    case v := <-active:  // selected
        fmt.Println("got:", v)
    }
}

متى تستخدمون القنوات غير المخزنة مؤقتًا

استخدموا القنوات غير المخزنة مؤقتًا عندما:

  • تحتاجون إلى تسليم متزامن مضمون
  • يجب أن تؤكد الغوروتين استلام القيمة قبل أن يتابع المرسل
  • تطبّقون إشارات المرور أو التحكّم في تدفق البيانات
  • تنشئون مسارات معالجة ينبغي لكل مرحلة فيها معالجة عنصر واحد في كل مرة

تحقق سريع

ماذا يحدث عند الإرسال إلى قناة غير مخزنة مؤقتًا من دون وجود مستقبل جاهز؟

مراجعة: القنوات غير المخزنة مؤقتًا

الملخص:

  • أنشئوها باستخدام make(chan T) — بسعة صفرية
  • يُحظر الإرسال حتى يصبح المستقبل جاهزًا؛ ويُحظر الاستقبال حتى يرسل المرسل
  • يجب أن يغلق المرسل القناة فقط
  • تكرّر range ch حتى إغلاق القناة
  • الاستقبال بقيمتين: v, ok := <-ch
  • استخدموا الأنواع أحادية الاتجاه للوضوح: chan<- و<-chan

الأسئلة الشائعة

هل درس «القنوات غير المخزَّنة» مجاني؟

نعم — نص درس «القنوات غير المخزَّنة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Go Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Go Academy 4 دروس في المجموع.

ماذا ستتعلم في «القنوات غير المخزَّنة»؟

تسليم متزامن بين Goroutines تتمرن على Go Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Go Academy؟

لا تُشترط خبرة سابقة. Go Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «القنوات غير المخزَّنة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Go Academy هذا؟

نعم. كل درس في Go Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. تشغيل Goroutines
  2. القنوات غير المخزَّنة
  3. القنوات المخزَّنة
  4. اتجاه القنوات وأنماط خطوط الأنابيب
← العودة إلى Go Academy