أهم 5 أخطاء لمطوري Go المبتدئين وكيفية تجنبها

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

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

ابدأ الدورة

مقدمة: لماذا تبدو Go بسيطة ولكنها تخفي فخاخًا

Go (Golang) هي لغة مترجمة، ومكتوبة بشكل ثابت، تم إنشاؤها في أعماق Google. غالبًا ما يتم الإشادة بها لبساطة بناء الجملة، والدعم المدمج للتوازي (concurrency)، والأداء العالي. ومع ذلك، فإن هذه البساطة الظاهرية غالبًا ما تلعب خدعة قاسية على المبتدئين القادمين من لغات ديناميكية (Python, JavaScript) أو حتى من C++.

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

1. تجاهل الأخطاء المرتجعة (Error Handling)

المشكلة

في Go لا توجد استثناءات (try-catch). الخطأ هو مجرد قيمة ترجعها الدالة كآخر وسيط. الخطأ الأكثر شيوعًا للمبتدئين هو تعيين النتيجة لمتغير، ولكن تجاهل الخطأ باستخدام الشرطة السفلية _.

// سَيء: تم ابتلاع الخطأresult, _ := doSomething()fmt.Println(result)

لماذا هذا سيء؟

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

الطريقة الصحيحة

تحقق دائمًا من الخطأ. استخدم النمط الاصطلاحي (idiomatic pattern):

// جيد: تمت معالجة الخطأresult, err := doSomething()if err != nil {    log.Printf("خطأ أثناء تنفيذ doSomething: %v", err)    return // أو panic، أو منطق آخر}fmt.Println(result)

نصيحة: اكتب الكود الخاص بك بحيث يصبح if err != nil رد فعل تلقائي لديك. لا تخف من الإرجاع المبكر (early return) — فهذا يجعل الكود أنظف.

2. الخلط بين nil والشرائح/الخرائط الفارغة

المشكلة

في Go، nil ليس "كائنًا فارغًا". إنها القيمة الصفرية (zero value) للمؤشرات (pointers)، والشرائح (slices)، والخرائط (maps)، والقنوات (channels)، والواجهات (interfaces). غالبًا ما يحاول المبتدئون كتابة بيانات في خريطة أو شريحة nil، مما يؤدي إلى حالة ذعر (panic).

// سَيء: حالة ذعر عند الكتابة في خريطة nilvar m map[string]intm["key"] = 42 // panic: assignment to entry in nil map

الطريقة الصحيحة

قم دائمًا بتهيئة الخرائط والشرائح قبل الاستخدام:

// جيد: التهيئة باستخدام makem := make(map[string]int)m["key"] = 42

// أو باستخدام حرفية (literal)m2 := map[string]int{}m2["key"] = 42

أما مع الشرائح فالوضع أكثر دقة: يمكن القراءة من شريحة nil (ستعيد شريحة فارغة)، لكن لا يمكن الكتابة فيها باستخدام الفهرس. استخدم append:

var s []ints = append(s, 1) // OK، سينشئ شريحة جديدة// s[0] = 1 // panic: runtime error: index out of range [0] with length 0

3. الاستخدام غير الصحيح للـ goroutines وسباق البيانات (Data Race)

المشكلة

الـ goroutines هي خيوط خفيفة الوزن. غالبًا ما يقوم المبتدئون بتشغيل goroutines متناسين مزامنة الوصول إلى البيانات المشتركة. يؤدي هذا إلى سباق البيانات (data race) — سلوك غير محدد للبرنامج.

// سَيء: سباق بياناتvar counter intfor i := 0; i < 1000; i++ {    go func() {        counter++ // غير آمن!    }()}time.Sleep(time.Second)fmt.Println(counter) // النتيجة غير متوقعة

الطريقة الصحيحة

استخدم الميوتكس (Mutexes) (sync.Mutex) أو القنوات (channels) للمزامنة:

// جيد: استخدام الميوتكسvar (    counter int    mu      sync.Mutex)for i := 0; i < 1000; i++ {    go func() {        mu.Lock()        counter++        mu.Unlock()    }()}// ننتظر الانتهاء (من الأفضل استخدام sync.WaitGroup)time.Sleep(time.Second)fmt.Println(counter) // 1000

مهم: تحقق دائمًا من الكود بحثًا عن سباقات البيانات باستخدام العلم -race: go run -race main.go.

4. أخطاء مع z

المدونات

توصيات الكتب