ProgrammationDéveloppeur Go

Quelles sont les particularités du travail avec les chaînes (string) en Go à connaître pour éviter des erreurs inattendues lors de la programmation ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Contexte de la question : En Go, les chaînes (string) sont un type de base souvent utilisé, activement utilisé pour l'échange de données, le logging, le parsing, etc. La particularité de Go est que les chaînes sont immuables, constituées d'une séquence de bytes immuable, et peuvent contenir des données en UTF-8.

Problème : La confusion entre le travail avec des chaînes et des slices de bytes ([]byte), provoquant des erreurs lors de la modification d'une chaîne, lors de la découpe par runes et lors de la tentative de travail avec des caractères multibytes (par exemple, cyrillique, emoji).

Solution :

Une chaîne est immuable, les éléments ne peuvent pas être modifiés directement — essayer de changer s[0] est incorrect. La chaîne est encodée en UTF-8, ce qui signifie qu'un symbole (rune) peut être plus large qu'un byte. Travailler avec []byte est moins coûteux, mais nécessite un contrôle manuel. La conversion string <-> []byte crée toujours une copie.

Exemple de code :

s := "привет" fmt.Println(len(s)) // 12 bytes (cyrillique : 2 bytes chacun) fmt.Println(len([]rune(s))) // 6 runes, autant de lettres fmt.Println(string([]byte{228, 189, 160, 229, 165, 189})) // caractères chinois

Caractéristiques clés :

  • Une chaîne est immuable, on ne peut pas changer par index.
  • Une chaîne est encodée en UTF-8, tous les symboles ne correspondent pas à un byte.
  • La conversion string <-> []byte crée une copie.

Questions pièges.

1. Peut-on changer un caractère spécifique d'une chaîne via un index (par exemple, s[1] = 'a') ?

Réponse : Non. Les chaînes sont immuables, le compilateur renverra une erreur. Il faut créer un nouveau slice []rune ou []byte, modifier, puis reconvertir en chaîne.

2. Pourquoi len(str) ne correspond-il pas toujours au nombre de caractères dans une chaîne ?

Réponse : len(str) est le nombre de bytes, pas de runes (symboles). Pour le cyrillique ou les emoji, une chaîne longue peut donner une valeur contre-intuitive. Pour le nombre de symboles, utilisez []rune :

s := "мир 😀" fmt.Println(len(s)) // 7 fmt.Println(len([]rune(s))) // 5

3. Une chaîne est-elle passée par référence ou par valeur à une fonction ?

Réponse : Par valeur, mais physiquement, elle contient un pointeur vers la mémoire et la longueur. Après le passage, les deux variables "pointent" vers le même texte, aucune copie n'est créée automatiquement. Une véritable copie de la mémoire apparaît lors de la conversion en []byte ou de []byte en string.

Erreurs typiques et anti-patterns

  • Essayer de modifier une chaîne directement par indexation.
  • Comparer la longueur d'une chaîne via len — erreurs avec Unicode.
  • Utiliser []byte pour la sérialisation, mais oublier l'encodage.
  • Oublier que string et []byte sont des objets différents en mémoire.

Exemple de la vie quotidienne

Cas négatif

Un développeur a une chaîne avec des caractères russes, il prend les 4 premiers bytes et s'attend à obtenir la première lettre, mais il n'obtient qu'une moitié de symbole — on obtient des "symboles cassés".

Avantages : Cela a été rapide et court. Inconvénients : Traitement incorrect des données Unicode, chaînes "cassées", panique lors de la tentative de parser de telles chaînes ailleurs.

Cas positif

Les chaînes sont converties en []rune pour travailler avec des symboles, après les actions nécessaires, la chaîne est reconstruite via string(). Le travail avec []byte est effectué uniquement pour la sérialisation de bas niveau, en tenant compte de l'encodage.

Avantages : Traitement correct de l'Unicode, fiabilité des fonctions. Inconvénients : Un peu plus lent, nécessite plus de mémoire, mais est sûr pour n'importe quelle chaîne.