الأساليب
Methods
الأساليب — Methods
في Go لا توجد كلاسات (Classes) كما في Java أو Python، لكن هناك بديل أنيق وقوي: الأساليب (Methods). الأسلوب هو ببساطة دالة مرتبطة بنوع معين. هذا يعني أنك تستطيع إضافة سلوك لأي نوع تُعرّفه — سواء كان struct أو حتى نوع بسيط مثل int.
تعريف أسلوب بسيط
الفرق بين الدالة العادية والأسلوب هو وجود مُستقبِل (Receiver) بين كلمة func واسم الدالة:
// دالة عادية — Regular function
func Area(width, height float64) float64 { ... }
// أسلوب على نوع — Method on a type
func (r Rectangle) Area() float64 { ... }
المُستقبِل (r Rectangle) يربط هذا الأسلوب بالنوع Rectangle. الآن يمكنك استدعاؤه عبر rect.Area().
مثال عملي
مستقبل القيمة vs مستقبل المؤشر — Value vs Pointer Receiver
هذا من أهم المفاهيم التي يجب أن تفهمها جيداً. عندما تُعرّف أسلوباً، المُستقبِل يمكن أن يكون:
- مستقبل قيمة
(r Rectangle)— يعمل على نسخة من القيمة - مستقبل مؤشر
(r *Rectangle)— يعمل على القيمة الأصلية نفسها
القاعدة الذهبية:
- إذا الأسلوب يُعدّل الكائن ← استخدم مستقبل مؤشر
*T - إذا الأسلوب يقرأ فقط ← مستقبل قيمة
Tيكفي - إذا الـ struct كبير ← مستقبل مؤشر أفضل (تجنب النسخ)
- في الممارسة: إذا أسلوب واحد يحتاج مؤشر، اجعل كل أساليب النوع بمؤشر للاتساق
الفرق العملي بين النوعين
لنرى ماذا يحدث عندما نستخدم مستقبل قيمة مع أسلوب يحاول التعديل:
أساليب على أنواع غير Struct
يمكنك تعريف أساليب على أي نوع تُعرّفه — ليس فقط struct:
مجموعة الأساليب — Method Sets
هذا مفهوم مهم لفهم الواجهات لاحقاً:
- القيمة من نوع
Tتستطيع استدعاء أساليبTفقط (مستقبل قيمة) - المؤشر من نوع
*Tيستطيع استدعاء أساليبTو*T(كلا النوعين)
عملياً Go يقوم بتحويل تلقائي في معظم الحالات، لكن هذا يُهم عند التعامل مع الواجهات.
أخطاء شائعة
خطأ 1: نسيان أن مستقبل القيمة يعمل على نسخة
// ❌ خطأ شائع — هذا لا يُعدّل الأصل
func (u User) UpdateName(name string) {
u.Name = name // تعديل على نسخة!
}
// ✅ الصحيح
func (u *User) UpdateName(name string) {
u.Name = name // تعديل على الأصل
}
خطأ 2: محاولة تعريف أسلوب على نوع من حزمة أخرى
// ❌ لا يمكنك تعريف أسلوب على int مباشرة
func (n int) Double() int { return n * 2 }
// ✅ عرّف نوعك الخاص
type MyInt int
func (n MyInt) Double() int { return int(n) * 2 }