Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

القنوات (Channels) والاتصال

جزء من قسم البرمجة كائنية التوجه في رحلة GO على Coddy. الدرس 60 من 107.

القنوات هي الآلية الأساسية في Go للتواصل بين goroutines. وبدلاً من مشاركة الذاكرة مباشرةً، ترسل goroutines القيم وتستقبلها عبر القنوات، وفقًا لفلسفة Go: "لا تتواصل عبر مشاركة الذاكرة؛ شارك الذاكرة عبر التواصل."

أنشئ قناة باستخدام الدالة make مع الكلمة المفتاحية chan:

messages := make(chan string)

استخدم عامل السهم <- لإرسال القيم واستقبالها. يشير السهم إلى اتجاه تدفق البيانات:

func main() {
    messages := make(chan string)
    
    go func() {
        messages <- "hello"  // أرسل إلى القناة
    }()
    
    msg := <-messages  // استقبل من القناة
    fmt.Println(msg)   // المخرجات: hello
}

بشكل افتراضي، تؤدي عمليات الإرسال والاستقبال إلى الحظر حتى يصبح الطرف الآخر جاهزًا. عندما ترسل "hello" الـgoroutine، فإنها تنتظر حتى تصبح main جاهزة للاستقبال. يوفر سلوك الحظر هذا مزامنة مضمّنة: لا حاجة إلى time.Sleep.

يمكنك إغلاق channel للإشارة إلى أنه لن يتم إرسال أي قيم أخرى. يمكن للمستقبِلين اكتشاف ذلك:

close(messages)

msg, ok := <-messages
if !ok {
    fmt.Println("Channel closed")
}

القنوات محددة النوع: لا يمكن لـ chan string حمل سوى السلاسل النصية. يضمن أمان الأنواع هذا أن تتواصل goroutine مع أنواع البيانات الصحيحة، مع اكتشاف الأخطاء في وقت الترجمة بدلًا من وقت التشغيل.

challenge icon

التحدي

سهل

لنَبْنِ نظام ترحيل للرسائل يوضّح كيفية تواصل goroutine من خلال القنوات. ستنشئ pipeline تتدفق فيها messages بين مراحل معالجة مختلفة، مع تشغيل كل مرحلة بشكل متزامن.

ستنظّم شفرتك عبر ملفين:

  • relay.go: Define pipeline معالجة الرسائل.

    أنشئ بنية Message تحتوي على الحقلين ID (int) وContent (string).

    نفّذ ثلاث دوال تمثّل مراحل مختلفة من pipeline:

    • Producer(messages []Message, out chan Message) - تستقبل شريحة من messages وترسل كل واحدة منها إلى قناة الإخراج. بعد إرسال جميع messages، أغلق القناة للإشارة إلى اكتمال العملية.
    • Transformer(in chan Message, out chan Message) - تستقبل messages من قناة الإدخال، وتحول محتوى كل message إلى أحرف كبيرة، ثم ترسل message المحوّلة إلى قناة الإخراج. عند إغلاق قناة الإدخال (يُكتشف ذلك باستخدام صيغة الاستقبال ذات القيمتين)، أغلق قناة الإخراج.
    • Consumer(in chan Message) []string - تستقبل جميع messages من قناة الإدخال وتجمعها في شريحة من السلاسل المنسّقة. يجب أن تتبع كل سلسلة التنسيق: Message [ID]: [Content]. أعد الشريحة عند إغلاق القناة.
  • main.go: أعدّ pipeline ونظّم تدفق messages المتزامن.

    اقرأ عدد messages، ثم اقرأ معرّف ومحتوى كل message. أنشئ messages وأعدّ قناتين لربط مراحل pipeline الثلاث. شغّل Producer وTransformer بوصفهما goroutines، ثم شغّل Consumer في goroutine الرئيسي لجمع النتائج. اطبع كل نتيجة في سطر منفصل.

سيتم توفير المدخلات التالية:

  • السطر 1: عدد messages (عدد صحيح)
  • الأسطر التالية: لكل message، سطران - معرّف message (عدد صحيح)، ثم محتواه (سلسلة نصية)

على سبيل المثال، إذا أُعطي:

2
1
hello world
2
go channels

فيجب أن يكون الناتج:

Message 1: HELLO WORLD
Message 2: GO CHANNELS

يتدفق pipeline على النحو التالي: Producer يرسل messages → Transformer يحوّلها إلى أحرف كبيرة → Consumer يجمع النتائج وينسّقها. يمثّل كل سهم قناة تربط بين مراحل متزامنة. استخدم الحزمة strings لإجراء التحويل إلى أحرف كبيرة.

جرّب بنفسك

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// اقرأ عدد الرسائل
	nLine, _ := reader.ReadString('\n')
	n, _ := strconv.Atoi(strings.TrimSpace(nLine))

	// اقرأ الرسائل
	messages := make([]Message, n)
	for i := 0; i < n; i++ {
		idLine, _ := reader.ReadString('\n')
		id, _ := strconv.Atoi(strings.TrimSpace(idLine))
		contentLine, _ := reader.ReadString('\n')
		content := strings.TrimSpace(contentLine)
		messages[i] = Message{ID: id, Content: content}
	}

	// TODO: أنشئ قناتين لربط مراحل خط الأنابيب

	// TODO: أطلق Producer كـ goroutine

	// TODO: أطلق Transformer كـ goroutine

	// TODO: شغّل Consumer في الـ goroutine الرئيسي واجمع النتائج

	// TODO: اطبع كل نتيجة في سطر منفصل
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Go عبر الإنترنت