דילוג לתוכן המרכזי
מודול 5 · שיעור 2 מתוך 522/50 בקורס~14 min
שיעורי מודול (2/5)

שיטות: ערך מול מקלט מצביע

שיטה ב-Go היא פונקציה עם מקלט: מיוחד פרמטר שהוכרז בין func לשם השיטה, המחייב את שיטה לסוג. אין מחלקות: ניתן להגדיר שיטות על כל סוג שמוכרז בחבילה הנוכחית.

תַחבִּיר

Go
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 הוא משתנה כמו כל משתנה אחר.

מקלט ערך מול מקלט מצביע

Go
// 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
}

עם מקלט מצביע ניתן לשנות את המקלט ואת השינויים נראים מחוץ לשיטה. עם מקבל ערך אתה לא יכול - היית שנה רק את העותק המקומי.

Go
p := Person{Name: "Ada"}
p.Rename("Grace")
fmt.Println(p.Name)   // "Grace" — change is visible

מתי להשתמש במקלט מצביע

כללים מעשיים, לפי סדר עדיפות:

  1. עליך לשנות את המקלט → מקלט מצביע. הֶכְרֵחִי.
  2. המבנה גדול (עשרות שדות, מערכים בפנים) → מצביע מקלט כדי למנוע עותקים יקרים.
  3. עקביות: אם לפחות בשיטה אחת בסוג יש מקלט מצביע, השתמש מקלט מצביע גם עבור האחרים. כנס חשוב מאוד עבור ממשקים (מודול 6).
  4. סוגי "ערך" קטנים, בלתי ניתנים לשינוי (זמן.זמן, מספרים מרוכבים, קטנים מבנים) → מקבל ערך, קריא יותר.

שיטות על טיפוסים שאינם מבנה

אתה יכול להגדיר שיטות על כל סוג NAMED המוצהר בחבילה שלך:

Go
type Celsius float64

func (c Celsius) ToFahrenheit() float64 {
    return float64(c)*9/5 + 32
}

t := Celsius(20)
fmt.Println(t.ToFahrenheit())  // 68

אינך יכול להגדיר אותם על סוגים מחבילות אחרות (למשל int, string): עליך תחילה צור סוג מקומי בשם.

נסה את זה

פעילות גופנית#go.m5.l2.e1
ניסיונות: 0טוען...

הוסף שיטת מחרוזת Greet() (מקלט ערך) לאדם שמחזירה 'ciao <Name>'.

טוען עורך...
הצג רמז

מקלט בסוגריים לפני שם השיטה.

הפתרון זמין לאחר 3 ניסיונות

פעילות גופנית#go.m5.l2.e2
ניסיונות: 0טוען...

הוסף שיטת Rename(n string) עם מקלט POINTER שמשנה את p.Name.

טוען עורך...
הצג רמז

מקלט מצביע: `(p *אדם)`.

הפתרון זמין לאחר 3 ניסיונות

Quiz#go.m5.l2.e3
מוכן

מתי כדאי להשתמש במקלט מצביע (p *T)?

Go
func (t ?T) M() { ... }
אפשרויות תשובה

לְסַכֵּם

  • שיטה = פונקציה עם מקלט: func (r T) Name(...) ... { ... }.
  • מקבל ערך: פועל על עותק; מקלט מצביע: פועל על המקור.
  • Go מבצעת את ההמרה T ↔ *T באופן אוטומטי באתר השיחה.
  • מקלט מצביע כאשר: מוטציה + מבנה גדול + עקביות עם שיטות אחרות מהסוג.
  • לעולם אל תערבב מקלטי ערך ומצביע על אותו סוג.
  • השיטות עוברות על סוגי NAMED בחבילה הנוכחית (כולל non-struct).