جملة 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!")
}يمنع هذا برنامجك من الانتظار إلى الأبد عندما قد لا تكتمل عملية القناة مطلقًا.
التحدي
سهللنَبْنِ مراقب خدمة يستخدم عبارة 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 واطبع النتيجة
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP في Go
الملفات الخارجيةمساحة العمل والـ Modules في Goالـ Packages والـ Importsالأسماء المصدرة مقابل غير المصدرةمقدمة إلى الـ OOP في Goالـ Structs كـ Classesتعريف الـ Methods في الـ Structsالـ Pointer Receivers مقابل الـ Value Receiversتهيئة الـ Structدوال الـ Constructorمراجعة - آلة حاسبة بسيطة4الواجهات
مقدمة في الواجهاتالتنفيذ الضمنيالواجهة كعقدالواجهة الفارغة (any)تأكيد النوع (Type Assertion)تبديل النوع (Type Switch)تركيب الواجهاتواجهات Stringer و Errorمراجعة - حاسبة الأشكال7التغليف
الحقول المصدرة وغير المصدرةالتغليف على مستوى الحزمةدوال الـ Getter والـ Setterإخفاء المعلومات في Goملخص - سجلات الطلاب10الأنواع العامة (Go 1.18+)
مقدمة في الأنواع العامةمعاملات الأنواعقيود الأنواعالـ Structs العامةحل بديل للـ Methods العامةملخص - المجموعات العامة13أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factoryنمط Abstract Factoryنمط Observerنمط Strategy2تعمق في الأنواع و Structs
الأنواع الأساسية والمركبةتعريفات الأنواع المخصصةStruct TagsStructs مجهولةStructs متداخلةالقيم الصفرية والافتراضيةمراجعة - دفتر العناوين5التركيب بدلاً من الوراثة
لماذا لا تدعم Go الوراثةأساسيات تضمين الـ Structترقية الـ Methodتضمين عدة Structsالتضمين مقابل التجميعحجب الـ Methods المضمنةملخص - الهيكل الهرمي للموظفين8معالجة الأخطاء و OOP
واجهة errorأنواع الأخطاء المخصصةتغليف الأخطاء (fmt.Errorf)أخطاء Sentinelerrors.Is() و errors.As()Panic و Defer و Recoverملخص - File Parser11المكتبة القياسية والبرمجة كائنية التوجه (OOP)
io.Reader و io.Writerواجهة sort.Interfaceواجهة fmt.Stringerencoding/json مع Structsواجهة http.Handlerمراجعة - نماذج REST API14أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبMiddleware كنمط مزين3المؤشرات والذاكرة
أساسيات المؤشرات في Goالمؤشرات إلى الـ Structsالتمرير بالقيمة مقابل التمرير بالمرجعدالة ()newGarbage Collection في Goملخص - بناء Linked List6تعدد الأشكال في Go
تعدد الأشكال عبر InterfacesDuck Typing في Goقواعد استيفاء الـ Interfaceمجموعات متعددة الأشكالحقن التبعيةمراجعة - معالج الدفع9التزامن والبرمجة كائنية التوجه (OOP)
أساسيات الـ Goroutinesالقنوات (Channels) والاتصالالقنوات المخزنة (Buffered) مقابل غير المخزنةجملة Selectsync.Mutex و sync.RWMutexsync.WaitGroupتصميم الـ Structs الآمنة للخيوط (Thread-Safe)مراجعة - Worker Poolتدرّب بنفسك: مترجم Go عبر الإنترنت