Le package fmt a trois familles de fonctions d'affichage, et chaque famille a les trois mêmes variantes :
| Fonction | La sortie va vers | Format |
|---|---|---|
Print, Println, Printf | la sortie standard | par défaut, par défaut avec espaces et retour à la ligne, chaîne de format |
Sprint, Sprintln, Sprintf | une string renvoyée | les trois mêmes styles |
Fprint, Fprintln, Fprintf | n'importe quel io.Writer (fichier, buffer, réponse HTTP) | les trois mêmes styles |
Errorf | une error renvoyée | chaîne de format, plus %w pour envelopper |
Println ajoute des espaces entre les opérandes et un retour à la ligne à la fin. Printf n'ajoute rien : vous écrivez \n vous-même. Print n'ajoute des espaces qu'entre deux opérandes qui ne sont ni l'un ni l'autre des chaînes, ce qui surprend assez pour que la plupart du code utilise Println ou Printf.
Verbes de format
Généraux
| Verbe | Affiche | Exemple de sortie |
|---|---|---|
%v | la valeur dans un format par défaut | {Ana 31 [admin]} |
%+v | les structs avec les noms des champs | {Name:Ana Age:31 Tags:[admin]} |
%#v | la syntaxe Go de la valeur | main.User{Name:"Ana", Age:31, Tags:[]string{"admin"}} |
%T | le type | main.User |
%% | un signe pourcentage littéral | % |
%+v est celui à utiliser pour déboguer. Un pointeur vers une struct s'affiche &{...} plutôt qu'une adresse. Les maps s'affichent avec les clés triées, donc la sortie est stable même si l'ordre d'itération des maps est aléatoire.
Entiers
| Verbe | Signification | fmt.Sprintf(verb, 255) |
|---|---|---|
%d | décimal | 255 |
%b | binaire | 11111111 |
%o | octal | 377 |
%O | octal avec le préfixe 0o | 0o377 |
%x / %X | hexadécimal, minuscules ou majuscules | ff / FF |
%#x | hexadécimal avec le préfixe 0x | 0xff |
%c | le caractère de ce point de code | ÿ |
%q | un littéral caractère entre apostrophes | 'ÿ' |
%U | format Unicode | U+00FF |
Flottants
| Verbe | Signification | fmt.Sprintf(verb, 1234.5678) |
|---|---|---|
%f | décimal, 6 chiffres après la virgule par défaut | 1234.567800 |
%.2f | décimal, 2 chiffres après la virgule | 1234.57 |
%e | notation scientifique | 1.234568e+03 |
%g | %e ou %f, le plus court des deux, sans zéros finaux | 1234.5678 |
%v | comme %g | 1234.5678 |
%.2f arrondit la valeur binaire exacte du flottant, donc fmt.Sprintf("%.2f", 2.675) donne 2.67 : le float64 le plus proche de 2,675 est légèrement en dessous. Ne formatez jamais de l'argent à partir d'un flottant ; gardez les centimes dans un entier.
Chaînes et octets
| Verbe | Signification | fmt.Sprintf(verb, "go\n") |
|---|---|---|
%s | la chaîne brute | go et un retour à la ligne |
%q | entre guillemets doubles, échappements visibles | "go\n" |
%x | hexadécimal de chaque octet | 676f0a |
% x | hexadécimal avec espaces | 67 6f 0a |
%s sur un []byte l'affiche comme du texte ; %v affiche les nombres ([104 105]).
Autres types
| Verbe | Type | Affiche |
|---|---|---|
%t | bool | true ou false |
%p | pointeur, slice, map, channel, func | l'adresse, comme 0xc000012345 |
%w | error (uniquement dans Errorf) | le message de l'erreur, et l'enveloppe |
Largeur, précision et remplissage
Entre % et le verbe, vous pouvez placer des flags, une largeur et une précision :
| Forme | Effet |
|---|---|
%5d | largeur 5, aligné à droite (remplissage à gauche avec des espaces) |
%-5d | largeur 5, aligné à gauche |
%05d | remplissage avec des zéros |
%.2f | 2 chiffres après la virgule |
%8.2f | largeur 8 et 2 décimales |
%.3s | au plus 3 caractères de la chaîne |
%+d | toujours afficher le signe |
%*d | largeur prise dans l'argument suivant |
Notez que %.0f de 2.5 affiche 2 : Go arrondit ici au pair le plus proche. Pour les chaînes, la largeur compte les runes, pas les colonnes affichées, donc les caractères CJK et les emojis peuvent encore désaligner un tableau. Pour des colonnes alignées de texte variable, text/tabwriter fait la mesure à votre place.
Indices d'arguments
%[n] choisit un argument par sa position, ce qui permet d'en réutiliser un :
fmt.Printf("%[2]s %[1]s\n", "world", "hello") // hello world
fmt.Printf("%d %[1]x %[1]b\n", 10) // 10 a 1010
Errorf et %w
fmt.Errorf construit une error à partir d'une chaîne de format. Avec %w, elle enveloppe aussi une autre erreur, pour que les appelants puissent encore détecter l'originale :
Utilisez %w quand les appelants peuvent avoir besoin de vérifier la cause, et %v quand vous la masquez volontairement. Depuis Go 1.20, un appel à Errorf peut contenir plusieurs verbes %w. La page sur la gestion des erreurs traite l'enveloppement en détail.
Formatage personnalisé avec String()
Tout type doté d'une méthode String() string contrôle la façon dont %v, %s et Println l'affichent :
%d contourne String() et affiche le nombre sous-jacent. Pour les types d'erreur, la méthode équivalente est Error() string, qui a priorité sur String().
Quand le verbe est faux
fmt ne provoque jamais de panic sur un format invalide. Il affiche le problème en ligne :
fmt.Printf("%d\n", "oops")
fmt.Printf("%d %d\n", 1)
fmt.Printf("%d\n", 1, 2)
%!d(string=oops)
1 %!d(MISSING)
1
%!(EXTRA int=2)
Cette sortie a tendance à arriver en production parce qu'elle ne fait rien planter. go vet détecte les trois à la compilation :
./main.go:8:2: fmt.Printf format %d has arg "oops" of wrong type string
./main.go:9:2: fmt.Printf format %d reads arg #2, but call has 1 arg
./main.go:10:2: fmt.Printf call needs 1 arg but has 2 args
Notes de performance
fmt prend chaque argument comme un any et inspecte son type à l'exécution (en passant par la réflexion pour les structs, slices et maps), ce qui convient pour les logs et l'affichage mais se mesure dans les boucles serrées. Pour convertir un seul nombre, strconv.Itoa et strconv.FormatFloat sont plus rapides que Sprintf. Pour construire une longue chaîne dans une boucle, écrivez dans un strings.Builder avec fmt.Fprintf(&b, ...) au lieu de concaténer des résultats de Sprintf.
Questions fréquentes
Quelle est la différence entre Println, Printf et Sprintf en Go ?
fmt.Println affiche ses arguments séparés par des espaces avec un retour à la ligne à la fin. fmt.Printf affiche selon une chaîne de format et n'ajoute pas de retour à la ligne. fmt.Sprintf formate comme Printf mais renvoie le résultat sous forme de chaîne au lieu de l'afficher. fmt.Errorf fait de même et renvoie une error.
Comment afficher une struct avec les noms des champs en Go ?
Utilisez %+v : fmt.Printf("%+v\n", user) affiche {Name:Ana Age:31}. %v affiche seulement les valeurs, {Ana 31}, et %#v affiche la syntaxe Go avec le type, main.User{Name:"Ana", Age:31}.
Comment formater un float avec 2 décimales en Go ?
Utilisez %.2f : fmt.Sprintf("%.2f", 3.14159) renvoie "3.14". Ajoutez une largeur pour aligner des colonnes, %8.2f, ou un signe moins pour aligner à gauche, %-8.2f. strconv.FormatFloat(f, 'f', 2, 64) donne le même résultat sans chaîne de format.
Que fait %w dans fmt.Errorf ?
%w formate une erreur comme %v et l'enveloppe en plus, donc la nouvelle erreur transporte l'originale. errors.Is et errors.As peuvent alors retrouver l'erreur enveloppée : err := fmt.Errorf("load config: %w", os.ErrNotExist) rend errors.Is(err, os.ErrNotExist) vrai. %w ne fonctionne que dans fmt.Errorf.
Pourquoi ma sortie affiche-t-elle %!d(string=...) ?
Le verbe ne correspond pas au type de l'argument, par exemple %d avec une chaîne. fmt affiche le problème en ligne au lieu de provoquer un panic : %!d(string=oops). Les arguments manquants s'affichent %!d(MISSING) et les arguments en trop %!(EXTRA int=2). go vet détecte les trois avant que vous lanciez le programme.