שיעורי מודול (1/5)
`fmt` מתקדם
החבילה fmt היא השער לכל I/O טקסטואליים ב-Go. לדעת זאת היטב פירושו כתיבת יומנים קריאים, שגיאות אינפורמטיביות ועיצוב ערכי באופן אידיומטי מבלי להזדקק לספריות חיצוניות.
ארבע המשפחות
fmt חושף פונקציות בארבע משפחות, המובחן על ידי קידומת:
Print*→ כותב אלos.Stdout(Print,Println,Printf).Fprint*→ כותב לכלio.Writer(Fprintln(os.Stderr, ...),Fprintf(file, ...)).Sprint*→ מחזירה מחרוזת ללא הדפסה (Sprintf,Sprintln).Errorf→ בונהerrorבפורמט.
fmt.Println("hello") // stdout
fmt.Fprintln(os.Stderr, "boom") // stderr
s := fmt.Sprintf("[%d]", 42) // "[42]"
err := fmt.Errorf("parse %q: %w", in, base) // wrapped errorההבדל בין Print ל-Println הוא רק הרווח בין ארגומנטים לשורה החדשה הנגררת: Println תמיד מוסיף \n, Print הפורמט Print לא עוקב אחר הפורמט של Print.
פעלים עיקריים
| פועל | מה זה עושה |
|---|---|
%v | ערך ברירת מחדל (קורא String() אם מיושם). |
%+v | מבנה עם שמות שדות. |
%#v | תחביר Go (שימושי עבור איתור באגים ותמונות מצב). |
%T | סוג דינמי של הערך. |
%d | מספר שלם בבסיס 10. |
%b %o %x %X | בינארי, אוקטלי, הקסדצימלי (אותיות קטנות/רישיות). |
%f %e %g | נקודה צפה: קבועה, אקספוננציאלית, קומפקטית. |
%s | מחרוזת (או error/Stringer). |
%q | מחרוזת מצוטטת בסגנון Go (כלולות בריחות). |
%c | תו Unicode (rune). |
%p | מצביע בהקסדצימלי. |
%w | מעטפת שגיאה (רק בתוך Errorf). |
type Point struct{ X, Y int }
p := Point{1, 2}
fmt.Printf("%v\n", p) // {1 2}
fmt.Printf("%+v\n", p) // {X:1 Y:2}
fmt.Printf("%#v\n", p) // main.Point{X:1, Y:2}
fmt.Printf("%T\n", p) // main.Pointרוחב, דיוק, דגלים
פעלים מספריים ומיתרים מקבלים רוחב ודיוק:
%6d→ רוחב מינימלי 6, ריפוד שמאלי עם רווחים.%-6d→ רוחב 6, ריפוד ימני (דגל-).%06d→ רוחב 6, ריפוד עם0(דגל0).%.2f→ דיוק 2 ספרות עשרוניות.%8.2f→ רוחב 8, דיוק 2.
fmt.Printf("|%6d|\n", 42) // | 42|
fmt.Printf("|%-6d|\n", 42) // |42 |
fmt.Printf("|%06d|\n", 42) // |000042|
fmt.Printf("|%8.2f|\n", 3.14)// | 3.14|עבור טבלאות מיושרות, רוחב קבוע + %-...s עבור עמודות טקסט הוא הדפוס הפשוט ביותר לפני המעבר ל-text/tabwriter.
%w וגלישת שגיאה
%w הוא מיוחד: הוא עובד רק בתוך fmt.Errorf ושומר על השגיאה המקורית בשרשרת, כך שerrors.Is וerrors.As יוכלו ללכת בה.
if _, err := os.Open(path); err != nil {
return fmt.Errorf("read config %q: %w", path, err)
}שימוש ב-%v במקום ב-%w מדפיס את הודעת השגיאה אך מפרק את השרשרת: אין פתיחה, אין errors.Is. כלל: אם אתה רוצה שהמתקשר יוכל להבחין בסוג השגיאה או בזהות, השתמש ב-%w (רק אחד לכל Errorf).
תרגילים
השתמש ב-fmt.Sprintf כדי לעצב את המחרוזת '[42]' מהמספר השלם 42, ואז הדפס אותה.
הפתרון זמין לאחר 3 ניסיונות
הדפס את ה-struct p עם הפועל %+v (הוא חייב לכלול את שמות השדות).
הפתרון זמין לאחר 3 ניסיונות
איזה פועל, בשימוש ב-fmt.Errorf, משמר את שרשרת השגיאות עבור errors.Is/As?
err := fmt.Errorf("read %q: ???", path, base)