יסודות המצביעים ב-Go
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GO של Coddy. שיעור 19 מתוך 107.
מצביע הוא משתנה ששומר את כתובת הזיכרון של משתנה אחר. במקום להחזיק ערך ישירות, הוא מחזיק את המיקום שבו הערך הזה נמצא בזיכרון. מצביעים הם יסוד מרכזי ב-Go וחיוניים למניפולציה יעילה של נתונים.
כדי ליצור מצביע, השתמש באופרטור & כדי לקבל את הכתובת של משתנה, ובאופרטור * כדי להצהיר על טיפוס מצביע או לגשת לערך שבכתובת הזו.
x := 42
p := &x // p מחזיק את כתובת הזיכרון של x
fmt.Println(p) // 0xc000018030 (כתובת זיכרון)
fmt.Println(*p) // 42 (הערך בכתובת הזו)האופרטור & פירושו "הכתובת של" והוא מחזיר מצביע. האופרטור *, כשמשתמשים בו על מצביע, פירושו "הערך בכתובת" והוא נקרא ביטול הפניה. אפשר גם לשנות את הערך המקורי דרך המצביע.
x := 10
p := &x
*p = 25 // שנה את הערך באמצעות מצביע
fmt.Println(x) // 25 (המשתנה המקורי השתנה)סוג מצביע נכתב כך: *T, כאשר T הוא הסוג שאליו מצביעים. למצביע אל int יש סוג *int.
var p *int // מצהיר על מצביע ל-int
x := 100
p = &x // p מצביע כעת על xערך האפס של מצביע הוא nil, כלומר הוא לא מצביע לשום דבר. ניסיון לבצע ביטול הפניה של מצביע nil גורם ל-panic בזמן ריצה, לכן יש לוודא תמיד שהמצביעים מאותחלים לפני השימוש.
אתגר
קלבואו נבנה תוכנית פשוטה להחלפת ערכים, שמדגימה את העוצמה של מצביעים לשינוי משתנים באמצעות כתובות הזיכרון שלהם.
תארגנו את הקוד שלכם בשני קבצים:
swap.go: צרו פונקציה בשםSwapValuesשמקבלת שני מצביעי*intכפרמטרים. הפונקציה צריכה להחליף בין הערכים שאליהם המצביעים מצביעים. לאחר הקריאה לה, כל משתנה צריך להכיל את הערך המקורי של המשתנה השני. הפונקציה לא מחזירה דבר; היא משנה את הערכים ישירות באמצעות המצביעים.main.go: קראו שני מספרים שלמים מהקלט ושמרו אותם במשתנים, ואז השתמשו בפונקציהSwapValuesשלכם כדי להחליף ביניהם. הדפיסו את שני הערכים לפני ההחלפה ואחריה כדי להציג את השינוי.
הקלטים הבאים יסופקו:
- שורה 1: המספר השלם הראשון
- שורה 2: המספר השלם השני
פורמט הפלט:
Before: a=[first] b=[second]
After: a=[first] b=[second]לדוגמה, עבור 10 ו-25, הפלט שלכם צריך להיות:
Before: a=10 b=25
After: a=25 b=10זכרו להשתמש באופרטור & כשמעבירים את המשתנים שלכם לפונקציה, ובאופרטור * בתוך הפונקציה כדי לגשת לערכים עצמם ולשנות אותם.
נסו בעצמכם
package main
import "fmt"
func main() {
// קרא שני מספרים שלמים מהקלט
var a, b int
fmt.Scanln(&a)
fmt.Scanln(&b)
// הדפס את הערכים לפני ההחלפה
fmt.Printf("Before: a=%d b=%d\n", a, b)
// TODO: קרא לפונקציה SwapValues עם מצביעים ל-a ול-b
// זכור להשתמש באופרטור & כדי להעביר כתובות
// הדפס את הערכים אחרי ההחלפה
fmt.Printf("After: a=%d b=%d\n", a, b)
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות OOP ב-Go
קבצים חיצונייםסביבת העבודה והמודולים של Goחבילות וייבואשמות מיוצאים לעומת שמות לא מיוצאיםמבוא ל-OOP ב-GoStructs כמחלקותהגדרת מתודות עבור Structsמקבלי Pointer לעומת Valueאתחול Structפונקציות Constructorחזרה – מחשבון פשוט4ממשקים
מבוא לממשקיםמימוש משתמעממשק כחוזהממשק ריק (any)אימות טיפוסמתג טיפוסיםהרכבת ממשקיםממשקי Stringer ו-Errorסיכום – מחשבון צורות7כימוס
שדות מיוצאים לעומת שדות לא מיוצאיםכימוס ברמת החבילהמתודות Getter ו-Setterהסתרת מידע ב-Goסיכום – רשומות תלמידים10Generics (Go 1.18 ומעלה)
מבוא ל־Genericsפרמטרים של טיפוסיםאילוצי טיפוסיםמבנים גנרייםפתרון עוקף למתודות גנריותסיכום – אוסף גנרי2העמקה בסוגים וב-Structs
סוגים בסיסיים ומורכביםהגדרות של סוגים מותאמים אישיתתגיות StructStructs אנונימייםStructs מקונניםערכי אפס וברירות מחדלסיכום – ספר אנשי קשר5קומפוזיציה במקום ירושה
למה ב-Go אין ירושהיסודות הטמעת Structקידום מתודותהטמעת כמה Structsהטמעה לעומת אגרגציההסתרת מתודות מוטמעותסיכום – היררכיית עובדים8טיפול בשגיאות ו-OOP
ממשק errorסוגי שגיאות מותאמים אישיתעטיפת שגיאות (fmt.Errorf)שגיאות Sentinelerrors.Is() ו-errors.As()Panic, Defer ו-Recoverסיכום – מנתח קבצים11ספרייה סטנדרטית ותכנות מונחה עצמים
io.Reader ו-io.Writersort.Interfaceהממשק fmt.Stringerencoding/json עם מבניםהממשק http.Handlerסיכום – מודלים של REST API3מצביעים וזיכרון
יסודות המצביעים ב-Goמצביעים למבניםהעברה לפי ערך לעומת לפי הפניההפונקציה new()איסוף אשפה ב-Goסיכום - בונה רשימה מקושרת6פולימורפיזם ב-Go
פולימורפיזם באמצעות ממשקיםטיפוס ברווז ב-Goכללי התאמה לממשקאוספים פולימורפייםהזרקת תלויותסיכום - מעבד תשלומים9מקביליות ו-OOP
יסודות GoroutinesChannels ותקשורתChannel עם חוצץ לעומת ללא חוצץפקודת Selectsync.Mutex ו-sync.RWMutexsync.WaitGroupתכנון Struct בטוח לשימוש במקבילסיכום - מאגר עובדים12מושגים מתקדמים בתכנות מונחה עצמים
דפוס האפשרויות הפונקציונליותדפוס Builder ב-Goשרשור מתודותכינויי טיפוסים לעומת הגדרותיסודות Reflectionסקירה כללית של יצירת קודתרגלו בעצמכם: קומפיילר Go אונליין