Generics في Go: دليل شامل للـ Generics

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

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

ابدأ الدورة

Generics في Go: لماذا تحتاجها وكيف تستخدمها



مع إصدار Go 1.18، ظهرت واحدة من أكثر الميزات المنتظرة في اللغة — الأدوية (البرمجة العامة). قبل ذلك، كان على المطورين إما تكرار الكود لأنواع بيانات مختلفة أو استخدام الواجهة الفارغة interface{} مع تحويل الأنواع لاحقًا. Generics تحل هذه المشكلة بشكل جذري. في هذه المقالة، سنشرح لماذا تحتاجها، وكيف تستخدمها عمليًا، وما هي المخاطر التي تنتظرك.



ما هي الأدوية ولماذا تحتاجها في Go؟



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



قبل ظهور الأدوية، استخدم مطورو Go نهجين رئيسيين:



  • تكرار الكود — كتابة دوال منفصلة لـ int و string و float64 إلخ.
  • الواجهة الفارغة — استخدام interface{} مع type assertion أو reflection، وهو ما كان غير آمن وبطيء.


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



صياغة Generics: معاملات الأنواع



الفكرة الأساسية للأدوية في Go هي معاملات الأنواع (type parameters). يتم تعريفها بين قوسين مربعين بعد اسم الدالة أو النوع.



لننظر إلى مثال بسيط — دالة تُرجع القيمة الأصغر من قيمتين:



package main

import "fmt"

// دالة عامة مع معامل النوع Tfunc Min[T comparable](a, b T) T { if a < b { return a } return b}

func main() { fmt.Println(Min[int](10, 20)) // 10 fmt.Println(Min[string]("a", "b")) // "a" fmt.Println(Min(3.14, 2.71)) // 2.71 (يتم استنتاج النوع تلقائيًا)}


هنا T هو معامل النوع. comparable هو قيد (constraint) يخبر أن النوع T يجب أن يدعم عوامل المقارنة. بدون هذا القيد، لن يسمح المترجم باستخدام <.



هام: يمكن لـ Go استنتاج معاملات الأنواع تلقائيًا من الوسائط، لذلك في معظم الحالات لا تحتاج إلى تحديدها صراحة.



القيود (Constraints) في أدوية Go



القيود هي عنصر أساسي في الأدوية. تحدد العمليات المسموح بها لمعاملات الأنواع. بدون قيود، لا يعرف المترجم أي الطرق أو العوامل يمكن تطبيقها على T.



في Go، هناك عدة قيود مدمجة:



  • any — مرادف لـ interface{}، يسمح بأي نوع.
  • comparable — يسمح بالأنواع التي تدعم == و !=.
  • constraints.Ordered — من الحزمة golang.org/x/exp/constraints، يسمح بجميع الأنواع المرتبة (الأرقام والسلاسل).


يمكنك أيضًا إنشاء قيودك الخاصة باستخدام الواجهات:



package main

import "fmt"

// قيد مخصص: يجب أن يحتوي النوع على طريقة String()type Stringer interface { String() string}

// دالة تعمل مع أي Stringerfunc Print[T Stringer](value T) { fmt.Println(value.String())}

type User struct { Name string}

func (u User) String() string { return "User: " + u.Name}

func main() { user := User{Name: "Alice"} Print(user) // User: Alice}


لاحظ: في Go 1.18+، يمكن استخدام الواجهات كقيود، ويمكن أن تحتوي ليس فقط على طرق ولكن أيضًا على أنوا

المدونات

توصيات الكتب