Introduction : la question éternelle de Stack Overflow
\n\nSi 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".
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\nPourquoi Go ne permet-il pas de déclarer un tableau constant ?
\n\nPour 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\nVoici un exemple simple qui NE se compilera pas :
\n\npackage 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\nLe 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.
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\nMéthode 1 : Utiliser une variable avec un commentaire "ne pas toucher"
\n\nLa 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\npackage 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\nLes 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\nMéthode 2 : Fonction getter (la bonne voie)
\n\nCette 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\npackage 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\nPourquoi 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
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\nMéthode 3 : Variable de paquet avec accès privé
\n\nSi 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\npackage 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\nDésormais, les utilisateurs de votre paquet peuvent seulement lire les données, mais pas les modifier. Idéal pour les bibliothèques.
\n\nMéthode 4 : Utilisation de iota pour des ensembles constants
\n\nEt si vous n'avez pas besoin des valeurs elles-mêmes, mais de leurs indices ? Par ex