كيف تجتاز مقابلة Go: أهم الأسئلة
Go (Golang) — واحدة من أكثر اللغات طلبًا لبناء تطبيقات الخادم عالية التحميل والخدمات المصغرة. غالبًا ما تختبر مقابلة مطور Go ليس فقط معرفة بناء الجملة، ولكن أيضًا فهم الآلية الداخلية: goroutines و channels و interfaces وإدارة الذاكرة. في هذه المقالة، سنستعرض أهم 10 أسئلة تُطرح غالبًا في المقابلات، مع أمثلة كود وشروحات.
1. ما الفرق بين array و slice؟
هذا سؤال كلاسيكي لاختبار فهم أساسيات Go.
- Array — هو تسلسل ثابت الطول من العناصر من نفس النوع. حجم المصفوفة هو جزء من نوعها.
- Slice — هو هيكل ديناميكي يشير إلى مصفوفة أساسية. يمكن للشريحة أن تنمو وتغير حجمها.
// Array — حجم ثابتvar arr [3]int = [3]int{1, 2, 3}// Slice — ديناميكيvar slc []int = []int{1, 2, 3}
// مهم: arr و [4]int هما نوعان مختلفان// يتم تمرير Slices بالإشارة (مؤشر إلى underlying array)نصيحة: إذا كنت بحاجة لتغيير الطول، استخدم slice. إذا كنت بحاجة لضمان حجم ثابت، استخدم array.
2. ما هي goroutines وكيف تعمل؟
Goroutine هي خيط تنفيذ خفيف الوزن يُدار بواسطة runtime الخاص بـ Go. على عكس خيوط نظام التشغيل (OS threads)، تمتلك goroutines مكدسًا أصغر (يبدأ من 2 كيلوبايت) ويتم التبديل بينها بسرعة.
- تشغيل goroutine:
go func() - تعمل goroutines في نفس مساحة العنوان، لذا يجب مزامنة الوصول إلى البيانات المشتركة (عبر channels أو mutexes).
package main
import ( "fmt" "time")
func printNumbers() { for i := 1; i <= 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(i) }}
func main() { go printNumbers() // تشغيل goroutine time.Sleep(1 * time.Second) // ننتظر الانتهاء fmt.Println("Main done")}مهم: الدالة الرئيسية لا تنتظر انتهاء goroutines. للمزامنة، استخدم sync.WaitGroup أو channels.
3. كيف تعمل channels؟
Channels هي "أنابيب" محددة النوع تتبادل من خلالها goroutines البيانات. توفر نقلًا آمنًا للبيانات دون أقفال صريحة.
- Unbuffered channel: يتم حظر المرسل حتى يقرأ المستقبل البيانات.
- Buffered channel: يتم حظر المرسل فقط عند امتلاء المخزن المؤقت.
ch := make(chan int) // غير مخزنchBuf := make(chan int, 3) // مخزن (سعة 3)
// إرسالgo func() { ch <- 42}()
// استقبالvalue := <-chfmt.Println(value)
// إغلاق القناةclose(ch)// القراءة من قناة مغلقة تُرجع القيمة الصفرية (zero value)سؤال شائع: ماذا يحدث إذا قرأت من قناة nil؟ — الإجابة: سيتم حظر goroutine إلى الأبد (deadlock).
4. ما هي interfaces في Go وكيف تختلف عن اللغات الأخرى؟
Interface في Go هو مجموعة من التواقيع (methods). على عكس Java أو C#، فإن تنفيذ interface في Go ضمني (duck typing): النوع يلبي interface تلقائيًا إذا قام بتنفيذ جميع تواقيعه.
type Speaker interface { Speak() string}
type Dog struct{}func (d Dog) Speak() string { return "Woof!" }
type Cat struct{}func (c Cat) Speak() string { return "Meow!" }
func makeSound(s Speaker) { fmt.Println(s.Speak())}
func main() { makeSound(Dog{}) // Woof! makeSound(Cat{}) // Meow!}لماذا هذا مهم: يسمح بكتابة كود مرن ومنخفض الاقتران. يمكن للـ interface الفارغ interface{} (أو any في Go 1.18+) تخزين قيمة من أي ن