دروس الوحدة (3/5)
الأدوية العامة (الإصدار 1.18+)
منذ Go 1.18 (مارس 2022)، معلمات النوع متاحة: يمكن تحديد معلمات الوظائف والأنواع على الأنواع. إنها تتيح لك كتابة Map، Filter، Set[T]، LinkedList[T] بدون تكرار التعليمات البرمجية وبدون interface{} + تأكيدات نوع وقت التشغيل.
الوظيفة العامة: النحو
func Map[T, U any](s []T, f func(T) U) []U {
out := make([]U, len(s))
for i, v := range s {
out[i] = f(v)
}
return out
}
doubled := Map([]int{1, 2, 3}, func(n int) int { return n * 2 })
// doubled is []int{2, 4, 6}ثلاثة عناصر جديدة:
[T, U any]بعد الاسم: يعلن عن معلمات النوع مع قيودها.any= قيد يقبل أي نوع (الاسم المستعار لـinterface{}منذ Go 1.18).- الاستدلال: الاتصال بـ
Map([]int{...}, ...)ليس عليك كتابةMap[int, int](...): يستنتج المترجمT=int, U=int.
في بعض الأحيان لا يكون الاستدلال كافيًا (على سبيل المثال، المُنشئات التي لا تحتوي على وسيطات T) ويلزم إنشاء مثيل صريح: New[*Server]().
القيود المضمنة
| القيد | معنى |
|---|---|
| محمي_INLINE_13 | أي نوع (== interface{}). |
| محمي_INLINE_15 | الأنواع ذات == و!=: رقمية، وسلسلة، ومنطقية، ومؤشرات، وقنوات، ومصفوفات/بنيات قابلة للمقارنة. |
comparable يسمح بالمساواة ولكن لا < أو >.
func Index[T comparable](s []T, x T) int {
for i, v := range s {
if v == x { return i }
}
return -1
}بالنسبة إلى </>، تحتاج إلى قيد مخصص.
القيد المخصص: اكتب النقابات
القيد هو واجهة مع عبارات "نوع العنصر":
type Ordered interface {
~int | ~int64 | ~float64 | ~string
}
func Min[T Ordered](a, b T) T {
if a < b { return a }
return b
}|= union: يقبل أيًا من الأنواع المدرجة.~int= "int أو أي نوع محدد كـtype X int" (بنفس النوع الأساسي). بدون~، فقطintبالضبط.
يمكن للقيد أيضًا خلط الأساليب وكتابة العناصر:
type Stringable interface {
~string
Len() int
}أنواع عامة
ليس فقط الوظائف: يمكن أن تحتوي البنيات والواجهات أيضًا على معلمات النوع.
type Set[T comparable] struct {
m map[T]struct{}
}
func NewSet[T comparable]() *Set[T] {
return &Set[T]{m: make(map[T]struct{})}
}
func (s *Set[T]) Add(v T) { s.m[v] = struct{}{} }
func (s *Set[T]) Has(v T) bool { _, ok := s.m[v]; return ok }
s := NewSet[string]()
s.Add("ada")لا يمكن للطرق إضافة معلمات نوع تتجاوز تلك الخاصة بالنوع: func (s *Set[T]) MapTo[U any](...) لا يتم تجميعها (قيود التصميم المتعمد).
متى تستخدم الأدوية الجنيسة
** نعم ** عندما:
- المنطق مطابق حقًا لعدة أنواع (المجموعات والخوارزميات والمساعدين مثل
Map/Filter/Reduce). - سيكون البديل هو تكرار الكود أو استخدام
interface{}+ تأكيدات النوع (فقدان أمان النوع).
لا متى:
- الواجهة التي تحتوي على طريقة أو طريقتين كافية وأكثر قابلية للقراءة (
io.Reader،fmt.Stringer). - أنت تقوم بتحديد المعلمات "لأنك تستطيع": حالة استخدام واحدة → إنشاء نسخة ملموسة منها.
تمارين
تعريف الوظيفة العامة Min[T Ordered](a, b T) T التي تقوم بإعادة تشغيلها باستخدام المشغل <. لقد تم طلب القيد.
الحل متاح بعد 3 من المحاولات
تنفيذ الخريطة[T, U Any](s []T, f func(T) U) []U: تطبيق على كل عنصر واستعادة الشريحة الجديدة.
الحل متاح بعد 3 من المحاولات
القيد النوعي المدمج يوافق على المشغل == أماه NON l'operatore <?
func Index[T ???](s []T, x T) int { ... }