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

جملة Select

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

تتيح عبارة select لـ goroutine الانتظار على عمليات متعددة على القنوات في الوقت نفسه. وهي تشبه عبارة switch، لكن كل حالة تتضمن إرسالًا إلى قناة أو استقبالًا منها. عندما تكون قنوات متعددة جاهزة، تختار select إحداها عشوائيًا.

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)
    
    go func() { ch1 <- "from channel 1" }()
    go func() { ch2 <- "from channel 2" }()
    
    select {
    case msg1 := <-ch1:
        fmt.Println(msg1)
    case msg2 := <-ch2:
        fmt.Println(msg2)
    }
}

من دون select، سيتوقف الاستقبال من ch1 حتى وصول البيانات، مما قد يؤدي إلى فقدان البيانات على ch2. باستخدام select، تتم معالجة القناة التي تستقبل البيانات أولًا.

تجعل حالة default التعليمة select غير حاجزة. تُنفَّذ فورًا إذا لم تكن أي قنوات جاهزة:

select {
case msg := <-messages:
    fmt.Println("Received:", msg)
default:
    fmt.Println("No message available")
}

يجمع نمط شائع بين select والمهلات باستخدام time.After، الذي يعيد قناة تتلقى قيمة بعد المدة المحددة:

select {
case result := <-ch:
    fmt.Println("Got result:", result)
case <-time.After(2 * time.Second):
    fmt.Println("Timeout!")
}

يمنع هذا برنامجك من الانتظار إلى الأبد عندما قد لا تكتمل عملية القناة مطلقًا.

challenge icon

التحدي

سهل

لنَبْنِ مراقب خدمة يستخدم عبارة select للتعامل مع مصادر بيانات متزامنة متعددة. سيستمع المراقب لديك إلى قنوات خدمة مختلفة في الوقت نفسه، ويستجيب بشكل مناسب عند وصول البيانات أو عند عدم توفر أي تحديثات.

ستنظّم التعليمات البرمجية عبر ملفين:

  • monitor.go: عرّف منطق مراقبة الخدمة باستخدام التعامل مع القنوات المستند إلى select.

    أنشئ بنية ServiceUpdate مع حقلي Name (سلسلة نصية) وStatus (سلسلة نصية).

    نفّذ دالة Monitor تستقبل ثلاث قنوات: primary chan ServiceUpdate وbackup chan ServiceUpdate وdone chan bool. يجب أن تستخدم هذه الدالة select للاستماع إلى القنوات الثلاث جميعًا في الوقت نفسه:

    • عند الاستلام من primary: أعد السلسلة المنسّقة Primary: [Name] is [Status]
    • عند الاستلام من backup: أعد السلسلة المنسّقة Backup: [Name] is [Status]
    • عند الاستلام من done: أعد Monitoring stopped

    نفّذ دالة CheckStatus تستقبل قناة واحدة هي updates chan ServiceUpdate، وتستخدم select مع حالة default لإجراء فحص غير حاجب:

    • إذا كان هناك تحديث متاح: أعد Update available: [Name]
    • إذا لم يتوفر أي تحديث (حالة default): أعد No updates pending
  • main.go: أعدّ القنوات واستعرض سلوك select الحاجب وغير الحاجب.

    اقرأ وضعًا من الإدخال يحدد السيناريو الذي سيتم تشغيله: primary أو backup أو stop أو check.

    بالنسبة إلى الأوضاع primary وbackup وstop: اقرأ أيضًا اسم الخدمة وحالتها. أنشئ القنوات الثلاث، وشغّل goroutine يرسل البيانات إلى القناة المناسبة استنادًا إلى الوضع، ثم استدعِ Monitor واطبع نتيجته.

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

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

  • السطر 1: الوضع (primary أو backup أو stop أو check)
  • السطر 2: اسم الخدمة
  • السطر 3: حالة الخدمة
  • السطر 4 (للوضع check فقط): send أو nosend

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

primary
Database
healthy

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

Primary: Database is healthy

وإذا أُدخل ما يلي:

check
Cache
active
nosend

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

No updates pending

جرّب بنفسك

package main

import (
	"fmt"
)

func main() {
	var mode string
	fmt.Scanln(&mode)

	var serviceName string
	fmt.Scanln(&serviceName)

	var serviceStatus string
	fmt.Scanln(&serviceStatus)

	// TODO: تعامل مع الأوضاع المختلفة: "primary", "backup", "stop", "check"
	
	// للأوضاع "primary", "backup", "stop":
	// - أنشئ ثلاث قنوات: primary, backup, done
	// - أطلق goroutine يرسل البيانات إلى القناة المناسبة
	// - استدعِ Monitor واطبع النتيجة
	
	// للوضع "check":
	// - اقرأ العلم الإضافي ("send" أو "nosend")
	// - أنشئ قناة مخزّنة بسعة 1
	// - إذا كان العلم "send"، أرسل تحديثًا إلى القناة
	// - استدعِ CheckStatus واطبع النتيجة
	
}
quiz iconاختبر نفسك

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

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

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