הממשק fmt.Stringer
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GO של Coddy. שיעור 75 מתוך 107.
הממשק fmt.Stringer קובע כיצד הטיפוסים שלך יוצגו בעת הדפסה. זהו אחד הממשקים הנפוצים ביותר למימוש ב-Go, והוא מוגדר בחבילה fmt:
type Stringer interface {
String() string
}כשמעבירים ערך אל fmt.Println, אל fmt.Printf עם %v, או לפונקציות דומות, Go בודקת אם הטיפוס מממש את Stringer. אם כן, Go קוראת למתודה String() כדי לקבל את ייצוג הטקסט.
type Temperature struct {
Celsius float64
}
func (t Temperature) String() string {
return fmt.Sprintf("%.1f°C", t.Celsius)
}
func main() {
temp := Temperature{Celsius: 23.5}
fmt.Println(temp) // 23.5°C
}ללא המתודה String(), הפלט היה מציג את מבנה ברירת המחדל: {23.5}. באמצעות מימוש Stringer, אפשר לשלוט בדיוק באופן שבו הטיפוס שלך מוצג.
הדבר שימושי במיוחד עבור טיפוסים שבהם ערכי השדות הגולמיים אינם מעבירים את המשמעות בבירור. טיפוס Duration עשוי להציג "2h 30m" במקום להציג ננו־שניות גולמיות, או שטיפוס User עשוי להציג שם בפורמט מעוצב במקום את כל השדות שלו.
אתגר
קלבואו נבנה מערכת למעקב אחר זמן שמציגה משכי זמן בפורמט ידידותי לאנשים! תממשו את הממשק fmt.Stringer כדי לקבוע איך הטיפוסים המותאמים אישית שלכם יוצגו בעת הדפסה.
תארגנו את הקוד שלכם בשני קבצים:
duration.go: הגדירו טיפוסים הקשורים לזמן עם ייצוגי מחרוזת מותאמים אישית.צרו מבנה
Durationששומר את המספר הכולל של הדקות כמספר שלם. ממשו את המתודהString()כך שבעת הדפסה, הערך יוצג בפורמט קריא, כמו2h 30mעבור 150 דקות, או0h 45mעבור 45 דקות. יש להציג תמיד את השעות ואת הדקות.צרו מבנה
Taskעם שדות עבורName(מחרוזת) ו-Time(Duration). ממשו אתString()עבור Task כדי להציג בפורמט[Name]: [duration], כאשר משך הזמן משתמש במתודת String משלו.main.go: בנו והציגו משימות עם משכי הזמן שלהן.קראו את מספר המשימות, ואז עבור כל משימה קראו את שמה ואת משכה בדקות. צרו מופעים של Task והדפיסו כל אחד מהם ישירות באמצעות
fmt.Println: הממשק Stringer יטפל בעיצוב באופן אוטומטי.לאחר הדפסת כל המשימות, חשבו והדפיסו את הזמן הכולל של כל המשימות בפורמט:
Total: [duration]
הקלטים הבאים יסופקו:
- שורה 1: מספר המשימות
- השורות הבאות: שם המשימה ומספר הדקות (שתי שורות לכל משימה)
לדוגמה, בהינתן:
3
Code Review
90
Meeting
45
Documentation
120הפלט שלכם צריך להיות:
Code Review: 1h 30m
Meeting: 0h 45m
Documentation: 2h 0m
Total: 4h 15mובהינתן:
2
Design
180
Testing
65הפלט שלכם צריך להיות:
Design: 3h 0m
Testing: 1h 5m
Total: 4h 5mבאמצעות מימוש Stringer, הטיפוסים שלכם משתלבים בצורה חלקה עם פונקציות ההדפסה של Go. במקום לראות שדות גולמיים של מבנים כמו {90}, תקבלו פלט בעל משמעות שמובן למשתמשים.
נסו בעצמכם
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// קרא את מספר המשימות
line, _ := reader.ReadString('\n')
numTasks, _ := strconv.Atoi(strings.TrimSpace(line))
// TODO: צור slice לאחסון המשימות
// TODO: עקוב אחר סך הדקות
for i := 0; i < numTasks; i++ {
// קרא את שם המשימה
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
// קרא את משך המשימה בדקות
minutesLine, _ := reader.ReadString('\n')
minutes, _ := strconv.Atoi(strings.TrimSpace(minutesLine))
// TODO: צור Task עם השם ו-Duration
// TODO: הדפס את המשימה (fmt.Println ישתמש בממשק Stringer)
// TODO: הוסף את הדקות לסך הכול
_ = name
_ = minutes
}
// TODO: הדפס את המשך הכולל בפורמט "Total: Xh Ym"
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
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 אונליין