Go للبرمجة النظامية: لماذا يحل محل C و C++

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

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

ابدأ الدورة

Go للبرمجة النظامية: لماذا لم يعد C القديم الجيد ضرورياً؟



لفترة طويلة، كان عالم البرمجة النظامية حكراً على لغتين عملاقتين: C و C++. لقد منحتا تحكماً كاملاً في الذاكرة، وسمحتا بتحسين كل بايت، وعملتا على أي "عتاد" - من المتحكمات الدقيقة إلى الحواسيب المركزية. ولكن مع القوة جاء الألم: إدارة الذاكرة اليدوية، أخطاء التجزئة (segfaults)، الترجمة الطويلة، والجدالات التي لا تنتهي حول كيفية كتابة Makefile بشكل صحيح.



ثم جاء Go (أو Golang). لغة تم إنشاؤها في أعماق Google بواسطة مهندسين سئموا انتظار تجميع C++. أخذوا أفضل ما في اللغات النظامية (السرعة، الترجمة إلى كود آلي، الوصول المباشر للعتاد) وأضافوا ما كان ينقص الجميع: سهولة Python، الـ Goroutines المدمجة، وجامع القمامة الذي لا يبطئ.



اليوم سنشرح لماذا Go للبرمجة النظامية ليست خدعة تسويقية، بل واقع. سترون أمثلة كود تعمل أسرع من نظيراتها في Python ولا تقل أداءً عن C++.



ما هي البرمجة النظامية باستخدام Go؟



البرمجة النظامية هي إنشاء برمجيات تعمل بالقرب من العتاد: أنظمة التشغيل، برامج التشغيل، حزم الشبكات، أنظمة الملفات، الحاويات (Docker مكتوب بـ Go!)، قواعد البيانات وخوادم الويب. سابقاً، كان يُستخدم فقط C/C++ لهذا الغرض. لكن Go يكسر هذه الصورة النمطية.



لماذا Go مناسبة للبرمجة النظامية:



  • الترجمة إلى كود أصلي - لا آلة افتراضية كما في Java أو Python.
  • الكتابة الثابتة - يتم اكتشاف الأخطاء في مرحلة الترجمة، وليس في الإنتاج.
  • جامع قمامة مدمج - نعم، مبرمجو الأنظمة أيضاً يتعبون من تسرب الذاكرة.
  • Goroutines - خيوط خفيفة تسمح بمعالجة آلاف الاتصالات دون تعقيد.
  • الترجمة المتقاطعة - تجمع على Linux، تشغل على Windows. بدون ألم.


لنقارن: كتابة خادم TCP بسيط بلغة C يتطلب 100+ سطر من الكود مع معالجة يدوية للمآخذ (sockets). في Go - 20 سطراً، وهو جاهز للإنتاج فوراً.



Go ضد C/C++: معركة الأداء



بالطبع، C لا تزال أسرع على المستوى الدقيق. لكن بالنسبة لـ 99% من المهام الحقيقية، الفرق غير ملحوظ، بينما تتفوق Go في سرعة التطوير والأمان. إليك بعض الأمثلة حيث تظهر Go أداءً أفضل:



1. العمل مع الشبكة

تم إنشاء Go لخدمات الشبكات. مكتبتها القياسية net/http هي النموذج المثالي. انظر إلى خادم HTTP هذا:



package main

import ( "fmt" "net/http")

func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "مرحباً، عالم البرمجة النظامية!")}

func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil)}


هذا الكود يعالج آلاف الطلبات في الثانية، مستخدماً جميع أنوية المعالج تلقائياً. في C++، سيتطلب ذلك كتابة مجموعة خيوط (thread pool)، كائنات مزامنة (mutexes) وظروف سباق (race conditions). في Go - فقط شغّل go run main.go.



2. العمل مع الذاكرة

في Go لا توجد مؤشرات تقليدية مع عمليات حسابية، لكن هناك مؤشرات آمنة وشرائح (slices). جامع القمامة محسّن بحيث تُقاس فترات التوقف بالميكروثانية. للمقارنة: في Java، يمكن لجمع القمامة أن "يجمد" التطبيق لثوانٍ.



مثال على العمل مع البايتات الخام (كما في البرمجة النظامية):



package main

import ( "fmt" "unsafe")

type Data struct { ID int32 Name [32]byte}

func main() { d := Data{ID: 42, Name: [32]byte{'H', 'e', 'l', 'l', 'o'}} // الحصول على مؤشر للهيكل ptr := unsafe.Pointer(&d) fmt.Printf("حجم الهيكل: %d بايت", unsafe.Sizeof(d)) // قراءة الذاكرة كتيار من البايتات bytes := (*[36]byte)(ptr) // 4 (int32)

المدونات

توصيات الكتب