Przejdź do głównej treści
eLearner.app
Moduł 8 · Lekcja 1 z 536/50 w kursie~10 min
Lekcje modułu (1/5)

Zaawansowane `fmt`

Pakiet fmt jest bramą do wszystkich tekstowych operacji we/wy w Go. Dobra znajomość oznacza pisanie czytelnych dzienników, błędów informacyjnych i idiomatyczne formatowanie wartości bez uciekania się do zewnętrznych bibliotek.

Cztery rodziny

fmt udostępnia funkcje w czterech rodzinach, rozróżnianych przedrostkiem:

  • Print* → zapisuje do os.Stdout (Print, Println, Printf).
  • Fprint* → zapisuje do dowolnego io.Writer (Fprintln(os.Stderr, ...), Fprintf(file, ...)).
  • Sprint* → zwraca string bez drukowania (os.Stdout0, os.Stdout1).
  • os.Stdout2 → buduje sformatowany os.Stdout3.
Go
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

Różnica pomiędzy Print i Println polega jedynie na spacji pomiędzy argumentami a końcowym znakiem nowej linii: Println zawsze dodaje , Print nie, Printf stosuje się do formatu.

Główne czasowniki

CzasownikCo to robi
KODEF0Wartość domyślna (wywołuje String(), jeśli jest zaimplementowana).
KODEF2Struktura z nazwami pól.
KODEF3Składnia Go (przydatna przy debugowaniu i migawkach).
KODEF4Dynamiczny typ wartości.
KODEF5Liczba całkowita o podstawie 10.
KODEF6Binarny, ósemkowy, szesnastkowy (małe/wielkie litery).
KODEF7Zmiennoprzecinkowy: stały, wykładniczy, zwarty.
KODEF8Ciąg (lub error/String()0).
KODEF11Ciąg cytowany w stylu go (w tym znaki ucieczki).
KODEF12Znak Unicode (String()3).
KODEF14Wskaźnik w formacie szesnastkowym.
KODEF15Zawijanie błędów (tylko w String()6).
Go
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

Szerokość, precyzja, flagi

Czasowniki numeryczne i łańcuchowe akceptują szerokość i precyzję:

  • %6d → minimalna szerokość 6, lewe wypełnienie ze spacjami.
  • %-6d → szerokość 6, prawe wypełnienie (flaga -).
  • %06d → szerokość 6, wypełnienie 0 (flaga 0).
  • %.2f → precyzja 2 cyfry dziesiętne.
  • %8.2f → szerokość 8, dokładność 2.
Go
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|

W przypadku tabel wyrównanych stała szerokość + %-...s dla kolumn tekstowych jest najprostszym wzorcem przed przejściem do text/tabwriter.

%w i zawijanie błędów

%w jest wyjątkowy: działa tylko wewnątrz fmt.Errorf i zachowuje oryginalny błąd w łańcuchu, dzięki czemu errors.Is i errors.As mogą go obejść.

Go
if _, err := os.Open(path); err != nil {
    return fmt.Errorf("read config %q: %w", path, err)
}

Użycie %v zamiast %w wypisuje komunikat o błędzie, ale przerywa łańcuch: bez rozpakowywania, bez errors.Is. Reguła: jeśli chcesz, aby osoba wywołująca była w stanie rozróżnić rodzaj lub tożsamość błędu, użyj %w (tylko jeden na Errorf).

Ćwiczenia

Ćwiczenie#go.m8.l1.e1
Próby: 0Ładowanie...

Użyj fmt.Sprintf, aby sformatować ciąg „[42]” z liczby całkowitej 42, a następnie wydrukuj go.

Ładowanie edytora...

Rozwiązanie dostępne po 3 próbach

Ćwiczenie#go.m8.l1.e2
Próby: 0Ładowanie...

Wydrukuj strukturę p z czasownikiem %+v (musi zawierać nazwy pól).

Ładowanie edytora...

Rozwiązanie dostępne po 3 próbach

Quiz#go.m8.l1.e3
Gotowe

Który czasownik użyty w fmt.Errorf zachowuje łańcuch błędów dla błędów.Is/As?

Go
err := fmt.Errorf("read %q: ???", path, base)
Opcje odpowiedzi