Introduction : pourquoi la conversion de slices d'interfaces est un casse-tête pour tout développeur Go
\n\nSi vous avez déjà écrit du code Go qui reçoit un []interface{} et tenté de le convertir en []string ou []int, vous avez sûrement rencontré ce message d'erreur agaçant du compilateur : cannot convert []interface{} to []string. C'est l'un des problèmes les plus fréquents sur Stack Overflow, cumulant des milliers de vues. Et ce n'est pas surprenant — à première vue, la logique suggère : "Si chaque élément est un interface{} qui contient une chaîne, pourquoi ne puis-je pas simplement convertir toute la slice ?"
La réponse réside dans la manière dont Go gère les types et la mémoire. La conversion de slices d'interfaces n'est pas un simple cast de type, mais une véritable copie de données. Dans cet article, nous allons décortiquer le problème de fond en comble : de la théorie aux exemples pratiques, en passant par des solutions prêtes à l'emploi que vous pourrez utiliser immédiatement dans vos projets.
\n\nD'ailleurs, si vous codez en Go et manipulez des types de données indéfinis — par exemple lors du parsing de JSON ou du traitement de données provenant de sources externes — ce sujet est crucial pour vous. C'est parti !
\n\nPourquoi Go interdit-il la conversion directe de []interface{} en []T ?
\n\nCommençons par les bases. En Go, interface{} est un type spécial qui stocke une paire : (type, valeur). Lorsque vous avez un []interface{}, chaque élément occupe un nombre différent d'octets en mémoire (selon le type stocké). En revanche, []string est un tableau contigu de structures string (chaque chaîne est un pointeur vers les données + une longueur).
Imaginez que vous ayez une boîte avec des balles de couleurs et de tailles variées (c'est []interface{}), et que vous deviez les transférer dans une boîte où toutes les balles sont de la même couleur et de la même taille ([]string). Vous ne pouvez pas simplement déplacer la boîte — il faut vérifier chaque balle, la sortir et la placer dans la nouvelle boîte. C'est exactement ce qui se passe lors de la conversion de slices d'interfaces.
Point clé : l'assertion de type (type assertion) ne fonctionne que sur des éléments individuels, pas sur la slice entière. Go n'offre pas de sucre syntaxique pour une conversion en masse — c'est fait exprès pour que vous contrôliez explicitement ce qui arrive à chaque élément.
\n\nExemple d'erreur que vous avez probablement déjà vue
\n\npackage main\n\nimport "fmt"\n\nfunc main() {\n data := []interface{}{"pomme", "banane", "cerise"}\n // Erreur de compilation :\n // cannot use data (variable of type []interface{}) as type []string in assignment\n // var fruits []string = data\n fmt.Println(data)\n}\n\n\nCe code ne compile pas. Le compilateur Go est strict sur les types, et la conversion implicite de slices de types différents est interdite. Même si vous êtes certain qu'elles ne contiennent que des chaînes.
\n\nLa bonne méthode : l'assertion de type pour chaque élément
\n\nLa manière la plus simple et la plus claire d'effectuer une conversion de slices d'interfaces est de parcourir chaque élément dans une boucle et d'appliquer une assertion de type (type assertion).
\n\nExemple de base avec type assertion
\n\npackage main\n\nimport "fmt"\n\nfunc convertToStrings(data []interface{}) []string {\n result := make([]string, 0, len(data))\n for _, v := range data {\n // On tente d'affirmer que v est une string\n if str, ok := v.(string); ok {\n result = append(result, str)\n } else {\n // Gestion d'erreur : l'élément n'est pas une chaîne\n fmt.Printf("Attention : l'élément %v n'est pas une chaîne, ignoré\\n", v)\n }\n }\n return result\n}\n\nfunc main() {\n mixte := []interface{}{"bonjour", 42, "monde", true, "golang"}\n chaines := convertToStrings(mixte)\n fmt.Println(chaines) /