Passer au contenu principal
eLearner.app
Module 6 · Leçon 4 sur 529/50 dans le cours~10 min
Leçons du module (4/5)

L'interface Stringer

fmt.Stringer est probablement l'interface standard la plus utilisée dans tous les pays. La bibliothèque standard de Go. C'est la démonstration parfaite de la puissance de petites interfaces.

Définition

Go
type Stringer interface {
    String() string
}

Une seule signature. Tout type qui définit String() string satisfait ça. Et fmt reconnaît cette interface : lorsque vous passez une valeur à fmt.Print*, s'il implémente Stringer, le résultat de String() est utilisé à la place de la représentation par défaut.

Exemple

Go
type Point struct{ X, Y int }

func (p Point) String() string {
    return fmt.Sprintf("(%d,%d)", p.X, p.Y)
}

fmt.Println(Point{1, 2})              // (1,2)
fmt.Printf("%v %s\n", Point{3, 4}, Point{5, 6})
// (3,4) (5,6)

La même valeur s'imprime avec un formatage personnalisé dans %v, %s, Println, Sprint, log, etc. Tout cela en définissant simplement une méthode.

Quand cela a du sens

  • Types qui modélisent un domaine (identifiants, codes, coordonnées, énumérations).
  • Erreurs avec une représentation lisible par l'homme (voir prochaine leçon sur error).
  • Les types que vous enregistrez souvent et pour lesquels vous souhaitez un format fixe.

Pas pour tout : si le type est simple et la représentation par défaut c'est bien, n'ajoute pas de bruit.

Types d'énumération : modèle commun avec iota

Go
type Status int

const (
    OK Status = iota
    WARN
    ERR
)

func (s Status) String() string {
    switch s {
    case OK:   return "OK"
    case WARN: return "WARN"
    case ERR:  return "ERR"
    default:   return "UNKNOWN"
    }
}

fmt.Println(OK, WARN, ERR)   // OK WARN ERR

Sans String(), fmt.Println(OK) imprimerait 0. Avec String(), il imprime le nom symbolique. Le stringer L'outil génère automatiquement ce modèle.

Attention à la récursion infinie

Go
type T int
func (t T) String() string {
    return fmt.Sprintf("%d", int(t))  // OK: cast to int breaks the recursion
}

Stringer sur un récepteur pointeur

Si String() possède un récepteur pointeur, seul *T satisfait Stringer. Avec fmt.Println(t) (une valeur), Go regarde l'ensemble de méthodes de T, ne le trouve pas et utilise le format par défaut. Pour éviter cela, valeur Le récepteur est généralement utilisé pour String() (c'est une "vue" ; ce n'est pas le cas). modifier quoi que ce soit).

Essayez-le

Exercice#go.m6.l4.e1
Tentatives : 0Chargement…

Implémentez String() sur Point pour qu'il renvoie (X,Y).

Chargement de l'éditeur…
Afficher l'indice

Utilisez `fmt.Sprintf` pour formater les champs.

Solution disponible après 3 tentatives

Exercice#go.m6.l4.e2
Tentatives : 0Chargement…

Implémentez String() sur un type Status (int) : 0 → 'OK', 1 → 'WARN', sinon → 'ERR'.

Chargement de l'éditeur…
Afficher l'indice

Allumez la valeur du récepteur ; n'oubliez pas de fournir une valeur par défaut.

Solution disponible après 3 tentatives

Quiz#go.m6.l4.e3
Prêt

Quelle signature la méthode doit-elle avoir pour satisfaire fmt.Stringer ?

Go
func (x T) ??? {}
Options de réponse

Récapitulatif

  • fmt.Stringer = interface { String() string }.
  • Son implémentation change la façon dont fmt.Print* représente le type.
  • Idiomatique pour les énumérations (iota), les types de domaines, les codes/identifiants.
  • N'appelez jamais fmt.Sprintf("%s", t) sur t à l'intérieur de String() (récursion).
  • Convention : récepteur de valeur pour String() (pas de mutation, évite les "surprises méthode-set").