Le langage de programmation Go a la réputation d’être simple à apprendre. Cependant, il recèle quelques pièges qui peuvent être difficiles à détecter pour un novice. Cette série d’articles propose d’en désamorcer quelques uns.
Nous voudrions inverser un slice. Cela semble une tâche toute trouvée pour les Generics, donc nous écrivons le code suivant:
package main
import "fmt"
func reverse[S []any](s S) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
func main() {
slice := []int{1, 2, 3}
reverse(slice)
fmt.Printf("%#v\n", slice)
}
Mais il ne compile pas, avec le message d’erreur suivant : []int does not implement []any
! Pourquoi ce code ne compile-t-il pas ? Comment le corriger ?
Tout d’abord, il faut indiquer que les Generics ne sont pas la cause du problème qui est plus fondamental et se résume à la question suivante : pourquoi ne peut-on envoyer le type []int
à une fonction qui attend []any
(ou []interface{}
) ?
Nous allons faire une démonstration par l’absurde et supposer que l’on puisse passer []int
à la fonction F([]interface{})
dans l’exemple suivant, qui devrait compiler :
package main
func F(v []interface{}) {
v[0] = "Oops!"
}
func main() {
v := []int{1, 2, 3}
F(v)
println(v[0])
}
Cet exemple ne compile pas avec le message d’erreur cannot use v (variable of type []int) as type []interface{} in argument to F
et nous comprenons maintenant pourquoi : cela permettrait d’assigner, dans notre exemple, une chaîne dans un slice d’entiers.
Pour revenir à notre problème de départ, nous devons trouver un moyen de décrire le type du paramètre de notre fonction reverse()
sans utiliser []any
.
Nous pouvons corriger le code comme suit :
package main
import "fmt"
func reverse[S []E, E any](s S) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
func main() {
slice := []int{1, 2, 3}
reverse(slice)
fmt.Printf("%#v\n", slice)
}
Nous indiquons alors au compilateur que notre argument est un slice du type E
et que le type E
est quelconque. Le compilateur est content, CQFD !
Pour une explication plus détaillée, voir cet article (en anglais).
Enjoy!