Concaténation de chaînes en Go : comment ne pas tuer les performances

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

Pourquoi une simple concaténation de chaînes en Go peut-elle devenir un problème ?

\n\n

Quiconque commence à étudier Go se heurte tôt ou tard à une tâche : il faut assembler plusieurs chaînes en une seule. La façon la plus évidente est d'utiliser l'opérateur += ou la simple addition +. Et cela fonctionne… jusqu'à ce que vous essayiez d'assembler mille chaînes. Soudain, votre code commence à ralentir et la mémoire se consomme comme lors d'un Black Friday.

\n\n

Pourquoi cela se produit-il ? En Go, les chaînes sont immuables (immutable). Lorsque vous écrivez s += "new", Go n'ajoute pas le texte à la fin de l'ancienne chaîne. Il crée une nouvelle chaîne, en copiant le contenu des deux parties. À chaque opération, une nouvelle mémoire est allouée. Si vous effectuez des milliers d'opérations de ce type, le garbage collector commence à fonctionner en mode urgence et les performances chutent.

\n\n

Dans cet article, nous allons analyser toutes les méthodes de concaténation de chaînes en Go : des plus naïves aux plus industrielles. Vous apprendrez quand utiliser chaque méthode et pourrez écrire un code dont vous n'aurez pas honte lors d'une revue de code.

\n\n

Méthodes de concaténation de chaînes en Go : du simple à l'efficace

\n\n

Examinons cinq approches principales. Pour chacune, je fournirai un exemple de code et expliquerai dans quelles situations elle est appropriée.

\n\n

1. Opérateur + et += (méthode naïve)

\n\n

La méthode la plus simple et la plus intuitive. Idéale pour assembler 2 à 5 chaînes.

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    hello := "Hello"\n    world := "World"\n    result := hello + ", " + world + "!"\n    fmt.Println(result) // Hello, World!\n}\n
\n\n

Quand l'utiliser : uniquement pour un petit nombre de chaînes. Si vous écrivez une boucle de 1000 itérations avec += — arrêtez-vous. C'est une complexité quadratique en mémoire (O(n²)).

\n\n

2. fmt.Sprintf

\n\n

Pratique lorsque vous devez formater une sortie. En interne, il crée également de nouvelles chaînes, mais le fait plus efficacement qu'un assemblage manuel.

\n\n
name := "Alice"\nage := 30\nresult := fmt.Sprintf("My name is %s and I am %d years old.", name, age)\nfmt.Println(result)\n
\n\n

Quand l'utiliser : lorsque vous devez non seulement assembler, mais aussi formater une chaîne avec différents types de données. Pour une simple concaténation, ce n'est pas le meilleur choix en raison des frais généraux d'analyse du modèle.

\n\n

3. strings.Join — le roi pour les slices de chaînes

\n\n

Si vous avez déjà un tableau ou une slice de chaînes, strings.Join est la méthode la plus rapide et la plus élégante.

\n\n
package main\n\nimport (\n    "fmt"\n    "strings"\n)\n\nfunc main() {\n    words := []string{"Go", "is", "awesome", "for", "backend"}\n    result := strings.Join(words, " ")\n    fmt.Println(result) // Go is awesome for backend\n}\n
\n\n

En interne, strings.Join calcule d'abord la longueur totale du résultat, alloue la mémoire une seule fois et la remplit. Aucune copie superflue.

\n\n

Quand l'utiliser : toujours lorsque vous avez une slice de chaînes prête. C'est l'option idéale pour construire des requêtes SQL, des chaînes CSV et des URL.

\n\n

4. bytes.Buffer — le classique du genre

\n\n

Le package bytes fournit un buffer qui croît dynamiquement. Il implémente l'interface io.Writer, vous pouvez donc y écrire via WriteString.

\n\n
package main\n\nimport (\n    "bytes"\n    "fmt"\n)\n\nfunc main() {\n    var buffer bytes.Buffer\n\n    for i := 0; i < 5; i++ {\n        buffer.WriteString("Line ")\n        buffer.WriteString(fmt.Sprintf("%d\\n", i))\n    }\n\n    fmt.Println(buffer.String())\n}\n
\n\n

Le buffer alloue la mémoire par blocs (généralement 64 octets), ce qui réduit considérablement le nombre d'allocations par rapport à +=.

\n\n

Quand l'utiliser : dans les boucles où le nombre de chaînes n'est pas connu à l'avance. Par exemple, lors de la génération de HTML ou de logs.

\n\n

5. strings.Builder — le standard moderne (Go 1.10+)

\n\n

Depuis Go 1.10, un

Blogs

Book Recommendations