عندما يتم تخزين القناة ، فإن هذا يعني أنه لن يتم حظره حتى يتم امتلاء المخزن المؤقت. بمجرد امتلاء المخزن المؤقت ، سيتم حظر Goroutine المرسل لأنه يحاول إضافة أشياء إلى القناة.
هذا يعني أن هذا سيحظر:
c := make(chan int)
c <- 1 // Block here, this is unbuffered !
println(<-c)
وهذه الإرادة ايضا الكتلة:
c := make(chan int, 2)
c <- 1
c <- 2
c <- 3 // Block here, buffer is full !
println(<-c)
لكن ال نقطة من goroutines والقناة هو على وجه التحديد تشغيل الأشياء في وقت واحد ، لذلك سوف ينجح هذا:
c := make(chan int)
go func() { c <- 1; }() // This will block in the spawned goroutine until...
println(<-c) // ... this line is reached in the main goroutine
وبالمثل:
c := make(chan int, 2)
go func() { // `go ...` spawns a goroutine
c <- 1 // Buffer is not full, no block
c <- 2 // Buffer is not full, no block
c <- 3 // Buffer is full, spawned goroutine is blocking until...
}()
println(<-c) // ... this line is reached in the main goroutine
في مثالك ، تفرخ أربعة goroutines المختلفة ، والتي تكتب جميعها أربعة أرقام إلى نفس القناة المخزنة. نظرًا لأن المخزن المؤقت هو 2 <16 ، فسوف ينتهي بهم المطاف إلى الحجب
لكن جوهر الأمر هو أن سياسة GO هي انتظر فقط من أجل goroutine الرئيسي:
يبدأ تنفيذ البرنامج عن طريق تهيئة الحزمة الرئيسية ثم استدعاء الوظيفة الرئيسية. عندما تعود الوظيفة الرئيسية ، يخرج البرنامج. لا ينتظر إكمال goroutines (غير مين).
هذا يعني أنه في المثال الأول ، رئيسي كان جوروتين يحظر عندما وصل إلى الخط c <- 3
. نظرًا لعدم تمكن Goroutine من فعل أي شيء يمكن أن يفصله ، اكتشف وقت التشغيل أن البرنامج قد تم مسدود وأبلغ عن خطأ.
في مثالك الثاني ، ومع ذلك ، ولدت كتلة goroutines ، بينما يستمر الرئيسي بهدوء حتى يصل إلى نهاية تنفيذها ، وعند هذه النقطة يتم قتل جميع goroutines (المحظورة) بصمت ، ولم يتم الإبلاغ عن أي خطأ.