Tranche vide en Go : initialisation correcte avec exemples

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Tranche vide en Go : comment ne pas se tromper dès le début

\n\n

Chaque développeur Go se retrouve tôt ou tard confronté à la question : "comment initialiser correctement une tranche vide ?". Une tâche apparemment simple, mais tout n'est pas si évident. Dans la FAQ officielle de Go et sur Stack Overflow, des centaines de commentaires et des milliers de votes sont consacrés à ce sujet. Pourquoi ?

\n\n

Parce qu'en Go, il existe deux manières fondamentalement différentes de créer une tranche vide, et le choix entre elles affecte les performances, la lisibilité du code et même le comportement lors de la sérialisation. Si vous codez en Go et souhaitez écrire un code propre et efficace sans surprises, cet article est pour vous.

\n\n

Nous allons analyser :

\n
    \n
  • La différence entre var s []int et s := make([]int, 0)
  • \n
  • Quand utiliser une nil-tranche et quand utiliser une tranche vide
  • \n
  • Comment cela affecte le JSON, la mémoire et les performances
  • \n
  • Ce que disent les gourous de Go et les auteurs de la bibliothèque standard
  • \n
\n\n

Deux frères jumeaux : nil slice vs empty slice

\n\n

En Go, une tranche est une structure composée de trois champs : un pointeur vers un tableau, la longueur et la capacité. Lorsque nous parlons de tranche vide, nous entendons une tranche de longueur 0. Mais la manière dont nous la créons a son importance.

\n\n

Méthode 1 : Déclaration var (nil slice)

\n\n
var s []int  // s == nil, len(s) == 0, cap(s) == 0
\n\n

C'est une nil-tranche. Elle ne pointe vers aucun tableau en mémoire. Cependant, vous pouvez librement appeler append dessus — Go allouera la mémoire automatiquement.

\n\n

Méthode 2 : Initialisation make (empty slice)

\n\n
s := make([]int, 0)  // s != nil, len(s) == 0, cap(s) == 0
\n\n

C'est une tranche vide. Elle pointe déjà vers un tableau zéro (un zerobase spécial dans le runtime Go).

\n\n

À première vue, la différence est imperceptible. Mais creusons un peu plus.

\n\n

Affichage console et JSON — premier piège

\n\n

Essayez d'exécuter ce code :

\n\n
package main\n\nimport (\n    "encoding/json"\n    "fmt"\n)\n\nfunc main() {\n    var nilSlice []int\n    emptySlice := make([]int, 0)\n\n    fmt.Printf("nilSlice: %v, is nil: %v\\n", nilSlice, nilSlice == nil)\n    fmt.Printf("emptySlice: %v, is nil: %v\\n", emptySlice, emptySlice == nil)\n\n    // Sérialisation JSON\n    nilJSON, _ := json.Marshal(nilSlice)\n    emptyJSON, _ := json.Marshal(emptySlice)\n\n    fmt.Printf("nilSlice JSON: %s\\n", nilJSON)\n    fmt.Printf("emptySlice JSON: %s\\n", emptyJSON)\n}
\n\n

Le résultat va vous surprendre :

\n\n
nilSlice: [], is nil: true\nemptySlice: [], is nil: false\nnilSlice JSON: null\nemptySlice JSON: []
\n\n

Voilà la principale surprise ! La sérialisation JSON se comporte différemment. Si votre API attend [] dans la réponse et que vous transmettez une nil-tranche — le client recevra null. Et cela casse les contrats.

\n\n

De nombreux clients REST (notamment en JavaScript) vérifient strictement : si un tableau est attendu dans la réponse et que null arrive — une erreur peut survenir ou la logique frontend peut être perturbée.

\n\n

Performances : y a-t-il une différence ?

\n\n

Réponse courte : oui, mais dans 99% des cas, elle est négligeable.

\n\n

Lorsque vous utilisez make([]int, 0), Go alloue immédiatement la mémoire pour la structure de la tranche (24 octets sur un système 64 bits) et la lie à zerobase. Avec var, l'allocation ne se produit qu'au premier append.

\n\n

Si vous créez une tranche qui restera probablement vide, la nil-tranche économise une allocation mémoire. Si vous savez avec certitude que vous allez ajouter des éléments — make avec indication de capacité offrira de meilleures performances :

\n\n
// Si vous connaissez la taille approximative — spécifiez la capacité\ns := make([]int, 0, 100)  // capacité 100, longueur 0\nfor i := 0; i < 100; i++ {\n    s = append(s, i)  // sans réallocations !\n}
\n\n

Mais pour la plupart des tâches applicatives, la différence est

Blogs

Book Recommendations