English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Golang دروس أساسية

Golang جمل التحكم

Golang دوال & طرق

Golang بنية

Golang قطع & مصفوفات

Golang نصوص (String)

Golang مراجع

Golang واجهات

Golang متوازي

Golang استثناء (Error)

Golang أخرى

الممرات (Channels) بلغة Go

في لغة Go، هي قناة وسيلة اتصال بين goroutine وآخر goroutine، وهي اتصال غير مشبك. بمعنى آخر، هي تقنية تسمح لـ goroutine بارسال البيانات إلى goroutine آخر. بشكل افتراضي، القناة ثنائية الاتجاه، مما يعني أن goroutine يمكنه إرسال أو استقبال البيانات من خلال نفس القناة، كما هو موضح في الشكل التالي:

إنشاء قناة

في لغة Go، يتم إنشاء قنوات باستخدام كلمة المفتاح chan، ويمكنها نقل نوع البيانات نفسه فقط، ولا يُسمح بنقل أنواع بيانات مختلفة عبر نفس القناة.

النص:

var Channel_name chan Type

يمكنك أيضًا استخدام تعريف مختصر عبر دالة make() لإنشاء قناة.

النص:

channel_name := make(chan Type)
package main
import "fmt"
func main() {
    // استخدام كلمة المفتاح var لإنشاء قناة
    var mychannel chan int
    fmt.Println("قيمة القناة:", mychannel)
    fmt.Printf("نوع القناة: %T", mychannel)
    // استخدم دالة make() لإنشاء قناة
    mychannel1 := make(chan int)
    fmt.Println("\nقيمة قناة channel1:", mychannel1)
    fmt.Printf("نوع قناة channel1: %T", mychannel1)
}

الإخراج:

قيمة القناة: <nil>
نوع القناة: chan int
قيمة قناة channel1: 0xc0000160c0
نوع قناة channel1: chan int

إرسال واستقبال البيانات عبر القناة

في لغة Go، تعمل القنوات بثلاث عمليات رئيسية، وهي الإرسال والاستقبال، وتُعرف هذه العمليات بـ "الإتصال". يعكس دالة <- اتجاه البيانات التي يتم إرسالها أو استقبالها. في القنوات، يتم تأخير العمليات حتى لا يكون هناك بيانات في الجانب الآخر بشكل افتراضي. هذا يسمح لـ goroutines بالتواصل مع بعضها البعض دون الحاجة إلى قفل أو متغيرات الحالة المحددة.

  1. عملية الإرسال:استخدام عملية الإرسال لتحويل البيانات من داخل goroutine إلى أخرى بمساعدة قناة. يمكن إرسال القيم مثل int،float64 وbool بسهولة وأمان عبر القنوات لأنها يتم نسخها، مما يعني عدم وجود خطر من الوصول المتوازي إلى نفس القيمة. بالإضافة إلى ذلك، فإن النصوص آمنة أيضًا لأنها غير قابلة للتغيير. ولكن، لا يمكن إرسال الإشارات أو المراجع (مثل المجموعات، المخططات، إلخ) عبر القنوات بطرق آمنة لأن قيم الإشارات أو المراجع قد تتغير عبر عملية الإرسال أو الاستقبال، مما يؤدي إلى نتائج غير قابلة للتنبؤ. لذلك، يجب التأكد من أن الإشارات أو المراجع تستخدم عبر القناة مرة واحدة فقط من قبل goroutine واحدة.

    Mychannel <- element

    تعني جملة أعلاه أن البيانات (element) في<-باستخدام دالة المساعدة إرسالها إلى القناة (Mychannel).

  2. عملية الاستقبال:استخدام عملية الاستقبال لاستقبال البيانات التي يرسلها الطرف المرسل.

    element := <-Mychannel

    تعني جملة أعلاه أن العنصر تم استقباله من قناة (Mychannel). إذا كان الناتج من الاستقبال غير متاح (لا يحتاج إلى استخدامه)، فإن الجملة صحيحة أيضًا. يمكنك أيضًا كتابة جملة receive مثل التالية:

    <-Mychannel
package main 
  
import "fmt"
  
func myfunc(ch chan int) { 
  
    fmt.Println(234 + <-ch) 
} 
func main() { 
    fmt.Println(بداية الطريقة الرئيسية) 
    //إنشاء قناة l 
    ch := make(chan int) 
  
    go myfunc(ch) 
    ch <- 23 
    fmt.Println(انتهاء الطريقة الرئيسية) 
}

الإخراج:

بداية الطريقة الرئيسية
257
انتهاء الطريقة الرئيسية

إغلاق القناة

يمكنك أيضًا إغلاق القناة بمساعدة دالة close(). إنها دالة مدمجة وتضبط علامة تشير إلى أن لا يوجد أي بيانات سيتم إرسالها إلى القناة.

النص:

close()

يمكنك أيضًا استخدام دورة for rangه لإغلاق القناة. هنا، يمكن لمسار المستقبل goroutine الاستفادة من الجملة المقدمة لتحقق مما إذا كانت القناة مفتوحة أو مغلقة:

ele, ok := <- Mychannel

في هذا السياق، إذا كانت قيمة ok صحيحة، فإن ذلك يعني أن القناة مفتوحة، لذا يمكن تنفيذ عملية القراءة. وإذا كانت القيمة false، فإن ذلك يعني أن القناة مغلقة، لذا لن يتم تنفيذ عملية القراءة.

//شرح برنامج Go
//إغلاق القناة المستخدمة
//دورات range و إغلاق الدالة
package main
import "fmt"
func myfun(mychnl chan string) {
    for v := 0; v < 4; v++ {
        mychnl <- "w3codebox"
    }
    close(mychnl)
}
func main() {
    //إنشاء قناة
    c := make(chan string)
    //استخدام Goroutine
    go myfun(c)
    //عندما تكون قيمة ok صحيحة، فإن ذلك يعني أن القناة مفتوحة، يمكن إرسال أو استقبال بيانات
    //عندما يتم تعيين قيمة ok إلى false، فإن ذلك يعني أن القناة مغلقة
    for {
        res, ok := <-c
        if ok == false {
            fmt.Println(قناة مغلقة، ok)
            قطع
        }
        fmt.Println("فتح القناة: ", res, ok)
    }
}

الإخراج:

فتح القناة: w3codebox: نعم
فتح القناة: w3codebox: نعم
فتح القناة: w3codebox: نعم
فتح القناة: w3codebox: نعم
إغلاق القناة: لا

ملاحظة هامة

  • حظر الإرسال والاستقبال:في القنوات، عند إرسال البيانات إلى القناة، يتم حظر جملة الإرسال حتى يتم قراءة البيانات من قبل goroutine آخر، بشكل مشابه، عند استقبال البيانات من قناة، يتم حظر جملة القراءة حتى يتم إرسال البيانات من قبل goroutine أخرى.

  • قناة بدون قيمة: قناةالقيمة الافتراضية هي nil.

  • حلقة For في القناة: يمكن للحلقة for مرور القيم المرسلة عبر القناة حتى يتم إغلاقها.

    النص:

    for item := range Chnl { 
         // جملة...
    }
    package main 
    import "fmt"
      
    func main() { 
      
        // استخدم دالة make() لإنشاء قناة
        mychnl := make(chan string) 
      
        // غوروتين مجهولة 
        go func() { 
            mychnl <- "GFG"
            mychnl <- "gfg"
            mychnl <- "Geeks"
            mychnl <- "w3codebox"
            close(mychnl) 
        } 
      
        // استخدام حلقة for
        for res := range mychnl { 
            fmt.Println(res) 
        } 
    }

    الإخراج:

    GFG
    gfg
    Geeks
    w3codebox
  • طول القناة:في القنوات، يمكنك استخدامدالة len()إيجاد طول القناة. هنا، الطول هو عدد القيم التي تقف في منطقة التخزين للقناة.

    package main 
      
    import "fmt"
    func main() { 
      
        // استخدم دالة make() لإنشاء قناة 
        mychnl := make(chan string, 4) 
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "w3codebox"
        // استخدم دالة len() للعثور على طول القناة 
        fmt.Println("طول القناة: ", len(mychnl)) 
    }

    الإخراج:

    طول القناة: 4
  • قدرة القناة:في القنوات، يمكنك استخدام دالة cap() لمعرفة قدرة القناة. هنا، قدرة الب缓冲 هو حجمه.

    package main
    import "fmt"
    func main() {
        // استخدم دالة make() لإنشاء قناة
        mychnl := make(chan string, 4)
        mychnl <- "GFG"
        mychnl <- "gfg"
        mychnl <- "Geeks"
        mychnl <- "w3codebox"
        // استخدم دالة cap() للعثور على قدرة القناة
        fmt.Println("قدرة القناة: ", cap(mychnl))
    }

    الإخراج:

    قدرة القناة: 5
  • Select و جملة case في القناة:في لغة go، جملة select تشبه جملة switch بدون أي معطيات إدخال. يمكن استخدام جملة select في القنوات لتنفيذ عملية واحدة من عدة عمليات مقدمة من مكتبات الحالات.