الكتاب الأساسي

مقدمة إلى Go

Go لغة برمجة مصرَّفة وثابتة الأنواع وُلدت في Google. يمتلك العديد من أعضاء الفريق الأساسي لتصميم Go وتطوير أدواتها سنوات عديدة من الخبرة في مجال أبحاث لغات البرمجة.

لـ Go مزايا كثيرة. بعضها فريد، وبعضها مستعار من لغات برمجة أخرى:

  • دعم مدمج للبرمجة المتزامنة — goroutines (خيوط خضراء) وبدء goroutines جديدة بسهولة.
  • القنوات (channels) (المبنية على نموذج CSP) وآليات select لإجراء عمليات مزامنة بين goroutines.
  • نوعا الحاوية map وslice مواطنان من الدرجة الأولى.
  • تعدد الأشكال عبر الواجهات.
  • تغليف القيم (value boxing) والانعكاس عبر الواجهات.
  • المؤشرات.
  • إغلاقات الدوال (function closures).
  • الطرق.
  • استدعاءات الدوال المؤجَّلة (deferred function calls).
  • تضمين الأنواع (type embedding).
  • استنتاج الأنواع (type deduction).
  • أمان الذاكرة.
  • جمع النفايات التلقائي.
  • توافق ممتاز عبر الأنظمة الأساسية.
  • الأجناس العامة المخصصة (custom generics) (منذ Go 1.18).
  • المكرِّرات المخصصة (custom iterators) (منذ Go 1.23).

إلى جانب المزايا أعلاه، ثمة معالم أخرى بارزة:

  • صُمِّم تركيب Go عمداً ليكون بسيطاً ونظيفاً ومشابهاً لغات البرمجة الشائعة الأخرى. وهذا يجعل تعلّم البرمجة بـ Go سهلاً.
  • تأتي Go مع مجموعة رائعة من حزم الشيفرة القياسية التي توفّر شتى الوظائف الشائعة. معظم هذه الحزم متوافقة عبر الأنظمة الأساسية.
  • تمتلك Go أيضاً مجتمعاً نشطاً، وهناك وفرة من مكتبات ومشاريع Go عالية الجودة من أطراف ثالثة يمكن استيرادها واستخدامها.

غالباً ما يُسمّى مبرمجو Go بـ gophers.

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

قابلية القراءة عامل مهم يؤثر تأثيراً كبيراً في تصميم Go. ليس صعباً على أي gopher فهم شيفرة Go التي كتبها gophers آخرون.

حالياً، أشهر مصرِّف لـ Go مكتوب بـ Go ويصونه فريق تصميم Go. سنسمّيه لاحقاً مصرِّف Go القياسي، أو gc (اختصار لمصرِّف Go، وليس لجمع النفايات GC). يصون فريق تصميم Go أيضاً مصرِّفاً ثانياً هو gccgo. استخدامه اليوم أقل شيوعاً من gc، لكنه يظل دائماً مرجعاً، وكلا المصرِّفين قيد التطوير النشط. وحتى الآن يركّز فريق Go على تحسين gc.

يُقدَّم gc ضمن Go Toolchain (مجموعة أدوات لتطوير Go يصونها فريق Go). صدرت Go Toolchain 1.0 في مارس 2012. يتوافق إصدار Go مع إصدار Go Toolchain. كان ولا يزال هناك إصداران رئيسيان يُصدَران كل عام.

منذ صدور Go 1.0، تغيّر تركيب Go قليلاً، لكن كانت ولا تزال هناك تحسينات كثيرة على أدوات Go Toolchain، من إصدار إلى إصدار، لا سيما gc. على سبيل المثال، يُعدّ التباطؤ الملحوظ الناجم عن جمع النفايات انتقاداً شائعاً للغات ذات الإدارة التلقائية للذاكرة. لكن منذ Go 1.8، ألغت التحسينات التي أُجريت على تنفيذ جمع النفايات المتزامن في gc مشكلة التباطؤ أساساً.

يدعم gc التصريف عبر الأنظمة الأساسية. على سبيل المثال، يمكننا بناء ملف تنفيذي لـ Windows على نظام تشغيل Linux، والعكس صحيح.

البرامج المكتوبة بلغة Go تُصرَّف في الغالب بسرعة كبيرة. زمن التصريف عامل مهم لسعادة التطوير. قصر زمن البناء أحد الأسباب التي تجعل كثيراً من المبرمجين يحبون البرمجة بـ Go.

مزايا الملفات التنفيذية لـ Go هي:

  • بصمة ذاكرة صغيرة
  • تنفيذ سريع للشيفرة (أسرع بكثير من لغات البرمجة النصية الديناميكية، لكنه أبطأ قليلاً من C/C++)
  • مدة إحماء قصيرة (وتجربة نشر رائعة)

قد تمتلك بعض اللغات المصرَّفة الأخرى، مثل C/C++/Rust، هذه المزايا الثلاث أيضاً (وقد تمتلك مزاياها الخاصة مقارنة بـ Go)، لكنها تفتقر إلى ثلاث خصائص مهمة في Go:

  • التصريف السريع يفضي إلى تجربة تطوير محلية سعيدة ودورات تكرار نشر قصيرة
  • المرونة، مثل اللغات الديناميكية
  • دعم مدمج للبرمجة المتزامنة

كل المزايا أعلاه مجتمعة تجعل Go لغة بارزة وخياراً جيداً لأنواع كثيرة من المشاريع، لا سيما تطبيقات الشبكات وأدوات النظام.

أخيراً، Go ليست مثالية في جميع الجوانب. هناك مقايضات معينة في تصميم Go. ولـ Go بالفعل بعض أوجه القصور. على سبيل المثال،

  • لا تدعم Go الآن قيماً غير قابلة للتغيير بشكل اعتباطي، ما يؤدي إلى تعريف كثير من القيم التي لا يُقصد تعديلها في الحزم القياسية كمتغيرات. وهذه نقطة ضعف أمنية محتملة لبعض برامج Go.
  • زيادة التعقيد والأخطاء في الإصدارات الأخيرة: أضافت التغييرات المُدخلة حديثاً في Go 1.22 و1.23 تعقيدات غير متوقعة وسلوكيات ضمنية إلى دلاليات اللغة. علاوة على ذلك، جلبت هذه التغييرات مشكلات عدم توافق خلفي وأخطاء، ويبدو أن القائمين على هذه التغييرات مترددون في حلها.