Go بالأمثلة: إغلاق القنوات (Closing Channels)

إغلاق القناة يشير إلى أنه لن يتم إرسال المزيد من القيم عليها. يمكن أن يكون هذا مفيداً لإبلاغ مستلمي القناة باكتمال العمل.

package main

import "fmt"

في هذا المثال سنستخدم قناة jobs لنقل العمل المطلوب القيام به من الـ goroutine الرئيسي إلى goroutine للعامل. عندما لا يكون لدينا المزيد من الوظائف للعامل، سنقوم بإغلاق قناة jobs.

func main() {
    jobs := make(chan int, 5)
    done := make(chan bool)

إليك goroutine للعامل. يستقبل باستمرار من jobs باستخدام j, more := <-jobs. في هذه الصيغة الخاصة للاستقبال بلقيمتين، ستكون قيمة more هي false إذا تم إغلاق القناة واستُلمت جميع القيم الموجودة بها بالفعل. نستخدم هذا للإخطار على done عندما ننتهي من جميع وظائفنا.

    go func() {
        for {
            j, more := <-jobs
            if more {
                fmt.Println("تم استلام الوظيفة", j)
            } else {
                fmt.Println("تم استلام جميع الوظائف")
                done <- true
                return
            }
        }
    }()

هذا يرسل 3 وظائف للعامل عبر قناة jobs ثم يغلقها.

    for j := 1; j <= 3; j++ {
        jobs <- j
        fmt.Println("تم إرسال الوظيفة", j)
    }
    close(jobs)
    fmt.Println("تم إرسال جميع الوظائف")

ننتظر العامل باستخدام نهج التزامن الذي رأيناه سابقاً.

    <-done

القراءة من قناة مغلقة تنجح فوراً، وتعيد القيمة الصفرية للنوع الأساسي. القيمة الثانية الاختيارية تكون true إذا كانت القيمة المستلمة قد سُلمت بواسطة عملية إرسال ناجحة، أو false إذا كانت قيمة صفرية ناتجة لأن القناة مغلقة وفارغة.

    _, ok := <-jobs
    fmt.Println("استلام المزيد من الوظائف:", ok)
}

تشغيل البرنامج:

$ go run closing-channels.go 
تم إرسال الوظيفة 1
تم استلام الوظيفة 1
تم إرسال الوظيفة 2
تم استلام الوظيفة 2
تم إرسال الوظيفة 3
تم استلام الوظيفة 3
تم إرسال جميع الوظائف
تم استلام جميع الوظائف
استلام المزيد من الوظائف: false

المثال التالي: التكرار عبر القنوات (Range over Channels).