دروس الوحدة (2/5)
الطرق: القيمة مقابل مستقبل المؤشر
الطريقة في Go هي وظيفة ذات مستقبل: خاص
المعلمة المعلنة بين func واسم الطريقة التي تربط
طريقة إلى نوع. لا توجد فئات: يمكن تعريف الأساليب على
أي نوع مسمى تم الإعلان عنه في الحزمة الحالية.
بناء الجملة
type Person struct {
Name string
}
func (p Person) Greet() string {
return "ciao " + p.Name
}
p := Person{Name: "Ada"}
fmt.Println(p.Greet()) // "ciao Ada"جهاز الاستقبال p Person يجعل Greet طريقة Person. داخل
الطريقة، p هي متغير مثل أي متغير آخر.
مستقبل القيمة مقابل مستقبل المؤشر
// VALUE receiver: operates on a COPY of the value
func (p Person) NameUpper() string {
return strings.ToUpper(p.Name)
}
// POINTER receiver: operates on the original value, can mutate it
func (p *Person) Rename(n string) {
p.Name = n
}باستخدام جهاز استقبال المؤشر يمكنك تعديل جهاز الاستقبال والتغييرات مرئية خارج الطريقة. مع متلقي القيمة لا يمكنك فعل ذلك تعديل النسخة المحلية فقط.
p := Person{Name: "Ada"}
p.Rename("Grace")
fmt.Println(p.Name) // "Grace" — change is visibleمتى تستخدم جهاز استقبال المؤشر
القواعد العملية حسب الأولوية:
- يجب عليك تعديل جهاز الاستقبال → جهاز استقبال المؤشر. إلزامي.
- البنية كبيرة (عشرات الحقول والمصفوفات بالداخل) → المؤشر المتلقي لتجنب النسخ باهظة الثمن.
- الاتساق: إذا كانت هناك طريقة واحدة على الأقل من النوع تحتوي على جهاز استقبال مؤشر، فاستخدم جهاز استقبال المؤشر للآخرين أيضا. اتفاقية مهمة جداً ل واجهات (الوحدة 6).
- أنواع "القيمة" الصغيرة وغير القابلة للتغيير (الوقت.الوقت، الأعداد المركبة، الصغيرة البنيات) → مستقبل القيمة، أكثر قابلية للقراءة.
طرق على الأنواع غير الهيكلية
يمكنك تعريف التوابع على أي نوع NAMED معلن في الحزمة الخاصة بك:
type Celsius float64
func (c Celsius) ToFahrenheit() float64 {
return float64(c)*9/5 + 32
}
t := Celsius(20)
fmt.Println(t.ToFahrenheit()) // 68لا يمكنك تحديدها على أنواع من الحزم الأخرى (على سبيل المثال int، string): يجب عليك
قم أولاً بإنشاء نوع محلي مسمى.
جربه
أضف أسلوب سلسلة Greet() (مستقبل القيمة) إلى الشخص الذي يُرجع "ciao <Name>".
إظهار التلميح
المتلقي بين قوسين قبل اسم الطريقة.
الحل متاح بعد 3 من المحاولات
أضف طريقة إعادة تسمية (سلسلة n) باستخدام جهاز استقبال POINTER الذي يغير p.Name.
إظهار التلميح
مستقبل المؤشر: `(ع * شخص)`.
الحل متاح بعد 3 من المحاولات
متى يجب عليك استخدام جهاز استقبال المؤشر (p*T)؟
func (t ?T) M() { ... }خلاصة
- الطريقة = الوظيفة مع جهاز الاستقبال:
func (r T) Name(...) ... { ... }. - مستقبل القيمة: يعمل على نسخة؛ مستقبل المؤشر: يعمل على الأصل.
- يقوم Go بإجراء التحويل
T↔*Tتلقائيًا في موقع الاتصال. - مستقبل المؤشر عند: الطفرة + البنية الكبيرة + التناسق مع الطرق الأخرى من النوع.
- لا تخلط مطلقًا بين مستقبلات القيمة والمؤشر من نفس النوع.
- يتم تنفيذ الطرق على أنواع NAMED في الحزمة الحالية (بما في ذلك غير البنية).