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

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

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

ابدأ الدورة

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



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



1. تجاهل الأخطاء المرتجعة



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



غير صحيح:

package main

import ( "fmt" "os")

func main() { file, _ := os.Open("config.txt") // نتجاهل الخطأ fmt.Println(file.Name())}


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



صحيح:

package main

import ( "fmt" "log" "os")

func main() { file, err := os.Open("config.txt") if err != nil { log.Fatalf("فشل فتح الملف: %v", err) } defer file.Close() fmt.Println(file.Name())}


نصيحة: تحقق دائمًا من err فور استدعاء الدالة. استخدم log.Fatal أو أعد الخطأ إلى أعلى المكدس، لكن لا تتجاهله أبدًا.



2. العمل غير الصحيح مع goroutines وسباقات البيانات



Goroutines هي خيوط خفيفة الوزن في Go. ومع ذلك، غالبًا ما يقوم المبتدئون بتشغيل goroutines دون الاهتمام بمزامنة الوصول إلى البيانات المشتركة. يؤدي هذا إلى سباقات البيانات (data race)، حيث تقرأ وتكتب عدة goroutines في نفس المتغير في وقت واحد.



غير صحيح:

package main

import ( "fmt" "sync")

func main() { counter := 0 var wg sync.WaitGroup

for i := 0; i < 1000; i++ { wg.Add(1) go func() { defer wg.Done() counter++ // سباق بيانات! }() } wg.Wait() fmt.Println(counter) // النتيجة قد تكون أي شيء (ليست 1000)}


صحيح (باستخدام mutex):

package main

import ( "fmt" "sync")

type Counter struct { mu sync.Mutex value int}

func (c *Counter) Increment() { c.mu.Lock() defer c.mu.Unlock() c.value++}

func (c *Counter) Value() int { c.mu.Lock() defer c.mu.Unlock() return c.value}

func main() { counter := &Counter{} var wg sync.WaitGroup

for i := 0; i < 1000; i++ { wg.Add(1) go func() { defer wg.Done() counter.Increment() }() } wg.Wait() fmt.Println(counter.Value()) // دائمًا 1000}


نصيحة: استخدم mutex (sync.Mutex) أو القنوات للمزامنة. قم بتشغيل الاختبارات مع العلم -race: go test -race.



3. الخلط بين slice من نوع nil و slice فارغ



في Go، يمكن أن تكون الـ slices إما nil أو فارغة. غالبًا لا يفهم المبتدئون الفرق، مما يؤدي إلى أخطاء أثناء التسلسل (JSON) أو تمرير الـ slices إلى الدوال.



  • Slice من نوع nil: يتم تعريفه كـ var s []int. ليس له مصفوفة أساسية.
  • Slice فارغ: يتم إنشاؤه كـ s := []int{} أو make([]int, 0). له مصفوفة أساسية، لكن طوله يساوي 0.


مثال على الخلط:

package main

import ( "e

المدونات

توصيات الكتب