func (T) M[P any](...)
method يعلن معامل نوع خاص به func (T) M[P any](...)
منذ Go 1.27، method مفرد يقدر يعلن معامل نوع خاص به بين اسمه وقائمة معاملاته — حتى لو النوع الذي ينتمي إليه غير عام أصلًا، بلا حاجة لتحويل النوع كله لنوع عام.
حتى Go 1.26 كان معامل النوع مسموحًا فقط بدالة كاملة بمستوى الحزمة (func F[T any](...)) أو بنوع عام كامل تحمل الـ methods الخاصّة به نفس معامل النوع (مثل Stack[T]). لم يكن ممكنًا لـ method مفرد أن يعلن معامل نوع منفصلًا خاصًّا به فقط.
منذ Go 1.27، هذا القيد أُزيل: تعريف method يقدر يكتب قوسًا مربّعًا بمعامل نوع مباشرة بعد اسم الدالة، تمامًا بنفس مكانه بدالة عامة عادية. النوع الذي يتبع له الـ method (المُستقبِل receiver) يبقى نوعًا عاديًا غير عام إن أردت — معامل النوع الجديد خاص فقط بذلك الاستدعاء الواحد.
قيد مهم: methods الواجهات (interfaces) لا يمكن أن تعلن معامل نوع خاصًّا بها، ولا يمكن لـ generic method أن تحقّق method مطلوبة بواجهة — لأن توقيع الواجهة لازم يبقى ثابتًا بغض النظر عن P المُمرَّر وقت الاستدعاء.
الصياغة
func (recv Receiver) MethodName[P Constraint](args) ReturnType
📄 مثال
type Registry struct {
name string
}
func (r Registry) Filter[T any](items []T, keep func(T) bool) []T {
var out []T
for _, v := range items {
if keep(v) {
out = append(out, v)
}
}
return out
}
r := Registry{name: "مستخدمون"}
r.Filter([]int{1, 2, 3, 4}, func(n int) bool { return n%2 == 0 }) // [2 4]أهم النقاط
| العنصر | الوظيفة |
|---|---|
| [P Constraint] | يُكتب بين اسم الـ method وقائمة معاملاته العادية، بنفس صياغة دالة عامة بمستوى الحزمة |
| Receiver | نوع المُستقبِل نفسه يبقى عاديًا غير عام إن أردت — معامل النوع الجديد خاص بالاستدعاء فقط |
| interfaces | methods الواجهات لا يمكن أن تعلن معامل نوع خاصًّا بها، ولا generic method تحقّق method مطلوبة بواجهة |
💡 نصائح عملية
- استخدمها لإضافة عملية عامة لنوع موجود أصلًا بدون تحويل النوع كله لنوع عام — مفيد بمكتبات تصدّر نوعًا محدَّدًا وتريد دالة مساعدة عامة عليه دون كسر الكود المستخدم له حاليًا
- لو النوع نفسه محتاج يحمل نفس معامل النوع بكل الحالات (مش استدعاء بحاله)، النوع العام الكامل (مثل Stack[T]) لسا الخيار الأنسب لا generic method
⚠️ أخطاء شائعة
- محاولة تعريف generic method داخل واجهة (interface) — غير مسموح لأن توقيع الواجهة لازم يبقى ثابتًا
- الخلط بين معامل نوع النوع نفسه ومعامل نوع الـ method — لو Receiver نفسه Stack[T] وأضفت method بمعامل نوع منفصل باسم T أيضًا، يتصادم الاسمان
🎓 تريد فهم الصورة الكاملة خطوة بخطوة؟ ابدأ من مسار GO الكامل بالعربي.