Tableaux constants en Go : comment les déclarer sans perdre la tête

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

Introduction : la question éternelle de Stack Overflow

\n\n

Si vous avez déjà cherché sur Google "Declare a constant array in Go", vous avez sûrement vu ce fameux sujet sur Stack Overflow avec des milliers de vues. Et oui, vous n'êtes pas seul dans votre confusion. En Go, on ne peut effectivement pas simplement écrire const arr = [...]int{1, 2, 3} — le compilateur vous répondra poliment "non".

\n\n

Pourquoi donc ? Et comment faire si nous avons besoin d'une liste de données immuable ? Dans cet article, nous allons comprendre la nature des constantes en Go, découvrir pourquoi les tableaux ne peuvent pas être des constantes, et trouver les meilleures solutions de contournement. Spoiler : il y a une solution, et elle est même plus élégante que vous ne le pensez.

\n\n

Pourquoi Go ne permet-il pas de déclarer un tableau constant ?

\n\n

Pour comprendre cela, il faut regarder sous le capot du langage. En Go, les constantes sont des valeurs immuables, calculées à la compilation. Elles doivent être strictement typées et connues avant l'exécution du programme. Les tableaux, quant à eux, sont des types de données composites qui occupent de la mémoire et peuvent être modifiés.

\n\n

Voici un exemple simple qui NE se compilera pas :

\n\n
package main\n\nconst arr = [3]int{1, 2, 3} // Erreur : const initializer [3]int{1, 2, 3} is not a constant\n\nfunc main() {\n    fmt.Println(arr)\n}
\n\n

Le compilateur dit : "Hé, ce n'est pas une constante !". Et il a raison. Même si le tableau est déclaré comme const, Go ne garantit pas que son contenu ne sera pas modifié via des pointeurs ou des slices. Les développeurs du langage ont donc décidé : pas de tableaux constants.

\n\n

Mais ne vous découragez pas trop vite. Il existe au moins trois façons de contourner cette limitation, et chacune a ses avantages.

\n\n

Méthode 1 : Utiliser une variable avec un commentaire "ne pas toucher"

\n\n

La méthode la plus simple et naïve est simplement de déclarer une variable et d'espérer que personne ne la modifie. Mais nous sommes des développeurs sérieux, n'est-ce pas ?

\n\n
package main\n\nimport "fmt"\n\n// arr - tableau constant. S'il vous plaît, ne le modifiez pas.\nvar arr = [3]int{1, 2, 3}\n\nfunc main() {\n    fmt.Println(arr)\n    // arr[0] = 100 // Décommentez — et tout casse\n}
\n\n

Les inconvénients sont évidents : ce n'est pas une vraie constante. N'importe qui peut modifier le tableau par affectation. Mais pour des prototypes rapides ou de petits projets, cela peut suffire.

\n\n

Méthode 2 : Fonction getter (la bonne voie)

\n\n

Cette approche est utilisée dans le code de production. Nous cachons le tableau à l'intérieur d'une fonction et retournons une copie. Ainsi, personne ne peut modifier l'original.

\n\n
package main\n\nimport "fmt"\n\n// getColors retourne une copie du tableau de couleurs.\n// Le tableau est protégé contre les modifications externes.\nfunc getColors() [3]string {\n    return [3]string{"Red", "Green", "Blue"}\n}\n\nfunc main() {\n    colors := getColors()\n    fmt.Println(colors)\n    // colors[0] = "Yellow" // Cela modifie la copie, pas l'original\n}
\n\n

Pourquoi est-ce bien ? Parce que :

\n
    \n
  • Le tableau ne peut pas être modifié de l'extérieur — la fonction retourne une copie.
  • \n
  • Le code est lisible et compréhensible.
  • \n
  • Facile à tester et à maintenir.
  • \n
\n\n

Mais il y a un détail : chaque appel de fonction crée une nouvelle copie du tableau. Si le tableau est grand (par exemple, 1000 éléments), cela peut être coûteux. Dans ce cas, utilisez la méthode suivante.

\n\n

Méthode 3 : Variable de paquet avec accès privé

\n\n

Si vous écrivez un paquet et souhaitez protéger le tableau des modifications, rendez-le non exportable (en minuscule) et donnez accès via une fonction.

\n\n
package constants\n\n// Tableau accessible uniquement à l'intérieur du paquet\nvar defaultPorts = [5]int{80, 443, 8080, 3000, 5000}\n\n// GetDefaultPorts retourne une copie du tableau de ports.\nfunc GetDefaultPorts() [5]int {\n    return defaultPorts\n}
\n\n

Désormais, les utilisateurs de votre paquet peuvent seulement lire les données, mais pas les modifier. Idéal pour les bibliothèques.

\n\n

Méthode 4 : Utilisation de iota pour des ensembles constants

\n\n

Et si vous n'avez pas besoin des valeurs elles-mêmes, mais de leurs indices ? Par ex

Blogs

Book Recommendations