Aller au contenu
Développement medium

Les pointeurs en Go

8 min de lecture

Go

Un pointeur, c'est l'adresse d'une valeur en mémoire plutôt que la valeur elle-même. Ce guide vous apprend à les utiliser en Go : lire une valeur à travers un pointeur, modifier une variable depuis une fonction, et éviter la panique du pointeur nil. C'est le concept qui décide si une fonction copie vos données ou les modifie sur place. Public visé : vous maîtrisez déjà les fonctions et les structures. Exemples testés sur Go 1.26.

  • Déclarer un pointeur avec & et lire sa valeur avec *.
  • Choisir entre passage par valeur et par pointeur.
  • Éviter les paniques sur un pointeur nil.
  • Comprendre pourquoi Go interdit l'arithmétique de pointeurs.

Deux opérateurs suffisent. L'esperluette & donne l'adresse d'une variable (on obtient un pointeur). L'étoile * fait l'inverse : elle déréférence le pointeur pour accéder à la valeur pointée.

x := 42
p := &x // p est un *int : l'adresse de x
fmt.Println(*p) // 42 : la valeur à cette adresse
*p = 100 // on écrit à travers le pointeur
fmt.Println(x) // 100 : x a changé

Modifier *p modifie x, car les deux désignent la même case mémoire. Un pointeur sur un int a le type *int, sur une struct Compte le type *Compte, et ainsi de suite.

C'est l'usage principal des pointeurs. Par défaut, Go passe les arguments par valeur : la fonction reçoit une copie. Pour qu'une fonction modifie l'original, on lui passe un pointeur.

type Compte struct {
Solde int
}
func crediterValeur(c Compte, montant int) { c.Solde += montant } // sur une copie
func crediterPointeur(c *Compte, montant int) { c.Solde += montant } // sur l'original
func main() {
c := Compte{Solde: 50}
crediterValeur(c, 10)
fmt.Println(c.Solde) // 50 : inchangé, on a modifié une copie
crediterPointeur(&c, 10)
fmt.Println(c.Solde) // 60 : l'original est modifié
}

crediterValeur travaille sur une copie qui disparaît à la fin de la fonction : l'original reste à 50. crediterPointeur reçoit l'adresse et modifie bien le compte. Le pointeur évite aussi de copier une grosse structure à chaque appel, ce qui compte pour la performance.

  • Quand la fonction doit modifier son argument.
  • Quand la structure est grosse et qu'une copie coûterait cher.
  • Pour un récepteur de méthode qui mute l'objet (voir les méthodes).

À l'inverse, pour de petites valeurs en lecture seule (un int, un petit struct), le passage par valeur est plus simple et souvent aussi rapide. Ne mettez pas des pointeurs partout par réflexe.

Un pointeur qui ne pointe vers rien vaut nil. Le déréférencer fait paniquer le programme (nil pointer dereference). C'est l'erreur la plus courante avec les pointeurs.

var np *Compte // déclaré mais pointe vers rien : nil
if np == nil {
fmt.Println("np est nil, on ne le déréférence pas")
}
np = &Compte{} // maintenant il pointe vers un Compte réel
np.Solde = 5 // OK
fmt.Println(np.Solde)

Le réflexe : vérifier != nil avant de déréférencer un pointeur dont l'origine est incertaine (retour de fonction, champ optionnel). Une fois initialisé avec &Compte{} ou new(Compte), il est sûr à utiliser.

Contrairement au C, Go interdit l'arithmétique de pointeurs : on ne peut pas faire p + 1 pour se déplacer en mémoire. C'est un choix de sécurité qui élimine toute une classe de bugs (débordements, corruption mémoire). Pour parcourir une suite d'éléments, on utilise un slice et range, pas un pointeur qu'on incrémente.

Un classique des pointeurs. Cherchez la solution avant d'ouvrir l'onglet Réponse.

Écrivez une fonction echanger qui inverse les valeurs de deux variables int, de sorte que l'appelant voie le changement.

  • Sa signature doit accepter deux pointeurs : func echanger(a, b *int).
  • Après echanger(&x, &y), x et y doivent avoir échangé leurs valeurs.

Indice : Go permet l'affectation multiple *a, *b = *b, *a en une ligne.

  • &x donne l'adresse de x (un pointeur) ; *p déréférence pour lire ou écrire la valeur pointée.
  • Go passe les arguments par valeur (copie) ; un pointeur permet à une fonction de modifier l'original.
  • Utilisez un pointeur pour muter un argument ou éviter de copier une grosse structure, pas par réflexe.
  • Un pointeur nil déréférencé fait paniquer : vérifiez != nil en cas de doute.
  • Go interdit l'arithmétique de pointeurs : pour parcourir des données, on utilise un slice, pas un pointeur incrémenté.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn