كيف تجتاز مقابلة Go: أهم الأسئلة المتقدمة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

المقابلة المتقدمة في Go: من الجوروتينات إلى الأدوية العامة

\n\n

مقابلة منصب مطور Go من المستوى المتوسط أو المتقدم ليست مجرد اختبار للصياغة. يتوقع أصحاب العمل فهماً عميقاً لنموذج التزامن، عمل بيئة التشغيل، إدارة الذاكرة وخصائص الكتابة. في هذه المقالة، سنناقش أهم الأسئلة المتقدمة في Golang التي ستساعدك على اجتياز المقابلة التقنية بثقة. لن نتوقف عند الأساسيات مثل "ما هي الشريحة" - بل سننتقل مباشرة إلى المواضيع المعقدة مع أمثلة الكود.

\n\n

1. الجوروتينات، القنوات وأنماط المزامنة

\n\n

الأسئلة حول الجوروتينات والقنوات هي كلاسيكية في أي مقابلة. ومع ذلك، على المستوى المتقدم، سيُسأل ليس فقط "ما هي الجوروتينة"، ولكن أيضاً عن تفاصيل عمل المجدول (نموذج GMP) والاستخدام الصحيح لأدوات المزامنة.

\n\n

سؤال: كيف يعمل مجدول الجوروتينات في Go؟ ما هي G، M، P؟

\n

يستخدم مجدول Go نموذج GMP: G (goroutine) - خيط خفيف، M (machine) - خيط نظام التشغيل، P (processor) - سياق التنفيذ. يرتبط P بمعالج منطقي ويدير قائمة انتظار الجوروتينات. عندما يتم حظر الجوروتينة (مثلاً، بسبب استدعاء نظام)، يمكن لـ P تبديل M إلى جوروتينة أخرى، مما يوفر تعدد مهام فعال دون إنشاء آلاف من خيوط نظام التشغيل.

\n\n

سؤال: ما الفرق بين القناة المخزنة مؤقتاً وغير المخزنة مؤقتاً؟ أعط مثالاً على deadlock.

\n\n
// قناة غير مخزنة مؤقتاً - تمنع المرسل حتى الاستلام\nch := make(chan int)\ngo func() {\n    ch <- 42 // محظورة حتى يقرأ main\n}()\nfmt.Println(<-ch) // 42\n\n// قناة مخزنة مؤقتاً - لا تمنع طالما المخزن المؤقت غير ممتلئ\nchBuf := make(chan int, 2)\nchBuf <- 1\nchBuf <- 2 // حسنًا، المخزن المؤقت غير ممتلئ\n// chBuf <- 3 // deadlock، إذا لم يكن هناك قارئ\n\n// deadlock نموذجي: قراءة من قناة غير مخزنة مؤقتاً فارغة\nchDead := make(chan int)\n// <-chDead // خطأ فادح: جميع الجوروتينات نائمة - deadlock!\n
\n\n

سؤال: كيف تغلق قناة بأمان؟ ما هو "range over channel"؟

\n

يجب على المرسل فقط إغلاق القناة. يمكن للمستقبل استخدام المعامل الثاني (v, ok := <-ch) للتحقق. ستنتهي التكرارية for v := range ch عند إغلاق القناة. محاولة الكتابة في قناة مغلقة تسبب panic.

\n\n
ch := make(chan int)\ngo func() {\n    for i := 0; i < 3; i++ {\n        ch <- i\n    }\n    close(ch) // نغلقها بالتأكيد\n}()\nfor v := range ch {\n    fmt.Println(v) // 0, 1, 2\n}\n
\n\n

2. الواجهات، الواجهة الفارغة وتأكيد النوع

\n\n

الواجهات في Go هي عقود. في المقابلة، من المهم فهم كيفية عملها داخلياً (هيكل iface و eface) وما الفرق بين الكتابة الثابتة والديناميكية.

\n\n

سؤال: ما هي الواجهة الفارغة (interface{}) ومتى تستخدمها؟

\n

الواجهة الفارغة لا تحتوي على دوال، لذا فإن أي نوع ينفذها. تُستخدم للعمل مع بيانات من نوع غير معروف (مثل json.Unmarshal). ومع ذلك، فإن الإفراط في استخدام الواجهة الفارغة ينتهك الكتابة الصارمة في Go وقد يؤدي إلى أخطاء وقت التشغيل.

\n\n

سؤال: كيف يعمل تأكيد النوع؟ ما الفرق بينه وبين تبديل النوع؟

\n\n
var val interface{} = "hello"\n\n// تأكيد النوع\nstr, ok := val.(string)\nif ok {\n    fmt.Println("هذه سلسلة:", str)\n}\n\n// تبديل النوع\nswitch v := val.(type) {\ncase string:\n    fmt.Println("سلسلة:", v)\ncase int:\n    fmt.Println("رقم:", v)\ndefault:\n    fmt.Println("نوع غير معروف")\n}\n
\n\n

سؤال: كيف تُخزن الواجهات في الذاكرة؟

\n

كل واجهة هي مؤشران: واحد للنوع (itable) والآخر للقيمة (data). بالنسبة للواجهة الفارغة (interface{}) مع

المدونات

توصيات الكتب