Модульні уроки (1/5)
Розширений `fmt`
Пакет fmt є шлюзом до всього текстового вводу-виводу в 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 ні, Printf відповідає формату.
Основні дієслова
| Дієслово | Що він робить |
|---|---|
%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 спроб
Надрукуйте структуру p із дієсловом %+v (вона має містити імена полів).
Рішення доступне після 3 спроб
Яке дієслово, використане у fmt.Errorf, зберігає ланцюжок помилок для errors.Is/As?
err := fmt.Errorf("read %q: ???", path, base)