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

Le motif de constructeur `New...`

Go n'a pas constructor comme mot-clé. La convention est une fonction d'usine qui renvoie correctement une valeur ou un pointeur initialisé. De par son nom, il est généralement appelé NewT (ou Newxxx).

Modèle de base : NewT

Go
type User struct {
    Name string
    Age  int
}

func NewUser(name string, age int) *User {
    return &User{Name: name, Age: age}
}

u := NewUser("Ada", 36)
fmt.Println(u.Name)

Avantages par rapport au littéral direct &User{...} :

  • Centraliser la validation et les valeurs par défaut.
  • Vous pouvez avoir des champs non exportés et les renseigner uniquement depuis le constructeur.
  • Changez l'implémentation sans interrompre les appelants.

Constructeur avec validation : (*T, erreur)

Lorsque l'initialisation peut échouer, renvoyez (*T, error) :

Go
import "errors"

func NewUser(name string, age int) (*User, error) {
    if name == "" {
        return nil, errors.New("nome obbligatorio")
    }
    if age < 0 {
        return nil, errors.New("eta non valida")
    }
    return &User{Name: name, Age: age}, nil
}

u, err := NewUser("Ada", 36)
if err != nil {
    // gestisci...
}

C'est le modèle idiomatique pour tout constructeur avec conditions préalables : connexion à la base de données, descripteur de fichier, configuration du serveur, etc.

Plusieurs constructeurs

Si vous disposez de plusieurs « façons » de construire, utilisez des noms descriptifs :

Go
func NewUser(name string) *User { ... }
func NewUserFromJSON(data []byte) (*User, error) { ... }
func NewAdmin() *User { ... }

Pas de surcharge dans Go : le nom sort du lot.

Options fonctionnelles (note avancée)

Lorsque les paramètres sont nombreux et facultatifs, le modèle idiomatique est "options fonctionnelles":

Go
type Option func(*Server)

func WithPort(p int) Option {
    return func(s *Server) { s.Port = p }
}

func WithTLS(cert, key string) Option {
    return func(s *Server) { s.Cert, s.Key = cert, key }
}

func NewServer(opts ...Option) *Server {
    s := &Server{Port: 8080} // default
    for _, opt := range opts {
        opt(s)
    }
    return s
}

s := NewServer(WithPort(9000), WithTLS("c.pem", "k.pem"))

Il est plus verbeux qu'un littéral mais s'adapte bien à de nombreux paramètres options et maintient la compatibilité ascendante (ajoutez un nouveau Option ne coupe pas les appelants existants).

Quand vous n'avez PAS besoin d'un constructeur

Si la valeur zéro du type est déjà utile, laissez l'appelant utiliser le littéral direct. Exemple canonique : sync.Mutex n'a pas de constructeur, var m sync.Mutex est déjà un mutex prêt. Idem pour bytes.Buffer.

La règle s'applique : « Rendre la valeur zéro utile ». Si tu réussis, rien constructeur obligatoire.

Essayez-le vous-même

Exercice#go.m5.l5.e1
Tentatives : 0Chargement…

Écrivez la fonction d'usine NewUser(name string, age int) *User qui renvoie &User{Name: name, Age: age}.

Chargement de l'éditeur…
Afficher l'indice

Utilisez le littéral `&User{...}` pour renvoyer un pointeur.

Solution disponible après 3 tentatives

Exercice#go.m5.l5.e2
Tentatives : 0Chargement…

Transformez NewUser en (chaîne de nom) (*Utilisateur, erreur) : si nom == '' renvoie nul, erreurs.Nouveau('nom requis').

Chargement de l'éditeur…
Afficher l'indice

S'il y a des conditions préalables, renvoyez (*T, erreur) et renvoyez nil + erreur en cas d'échec.

Solution disponible après 3 tentatives

Quiz#go.m5.l5.e3
Prêt

Quelle est la convention idiomatique pour les constructeurs dans Go ?

Go
// Quale firma è più idiomatica?
Options de réponse

Récapitulatif

  • Rien constructor : une fonction NewT est utilisée (ou New à l'intérieur du package du même nom).
  • Renvoie *T pour le cas simple ; (*T, error) avec préconditions ou validation.
  • En erreur : renvoie nil comme pointeur, l'erreur explicative comme deuxième valeur.
  • Pas de surcharges ; utilisez des noms descriptifs (NewUserFromJSON, NewAdmin).
  • "Rendre la valeur zéro utile" : si vous réussissez, le constructeur ne sert à rien.
  • Modèle avancé pour de nombreux paramètres optionnels : options fonctionnelles.