Pourquoi les Slices ?
Le problème avec un tableau c’est qu’il a une taille fixe, il faut donc absolument connaître sa taille au moment de sa déclaration ce qui n’est pas vraiment évident car on peut très vite s’apercevoir plus tard dans notre code que la taille allouée au départ à notre tableau est insuffisante.
Et c’est là qu’interviennent les Slices dans Go, Ils vont nous permettre d’avoir un tableau flexible et le dimensionner de façon dynamique sans se soucier de sa taille pendant sa déclaration.
Déclarer une Slice
Il existe deux façons pour créer une Slice.
Soit à partir de la même syntaxe qu'un tableau sauf que cette fois-ci on ne spécifie pas la taille du tableau :
package main
import (
"fmt"
)
func main() {
var nombres = []int{0, 0, 0, 0, 0} // création d'une slice avec 5 éléments
fmt.Println(nombres)
}
Résultat :
[0 0 0 0 0]
Soit depuis la fonction make()
package main
import (
"fmt"
)
func main() {
var nombres = make([]int, 5) // création d'une slice avec 5 éléments
fmt.Println(nombres)
}
Résultat :
[0 0 0 0 0]
Rajouter un élément dans une Slice
Pour rajouter un élément dans votre slice il faut utiliser la fonction append(), qui prend comme paramètres d'abord votre slice et ensuite l'élément que vous voulez rajouter et elle vous retournera une nouvelle Slice avec l'élément rajouté.
package main
import "fmt"
func main() {
var mois []string
mois = append(mois, "Janvier")
fmt.Println(mois)
mois = append(mois, "Février")
fmt.Println(mois)
}
Résultat :
[Janvier]
[Janvier Février]
Supprimer un élément dans une Slice
Il n'existe pas spécialement de fonction dans Go qui permet de supprimer un élément, mais il est possible de réutiliser la fonction append() pour supprimer un élément en Go.
Avant de vous montrer comment faire pour supprimer n'importe quel élément d'une slice, laissez-moi avant vous expliquer comment fonctionne la fonction append().
Voici à quoi ressemble le prototype de la fonction append() :
func append(slice []Type, elems ...Type) []Type
La fonction append() prend comme premier argument une Slice, le second paramètre est quant à lui est un paramètre variadique c'est-à-dire qu'il prend en compte un nombre indéterminé de paramètres.
Comme il est possible de rajouter un nombre indéterminé de paramètres sur le deuxième paramètre de la fonction append() , alors pour supprimer un élément il suffit de concaténer les éléments qui sont avant l'élément qu'on souhaite supprimer dans notre slice avec les éléments qui sont après l'élément qu'on souhaite supprimer dans notre slice.
Ce qui nous donne :
package main
import "fmt"
func main() {
mois := []string{"Janvier", "Février", "Mars", "Avril", "Juin", "Juillet"}
fmt.Println(mois)
// index à supprimer de notre slice
indexASupprimer := 1
// Suppression de l'index 1 du tableau soit "Février"
mois = append(mois[:indexASupprimer], mois[(indexASupprimer+1):]...)
fmt.Println(mois)
}
Résultat :
[Janvier Février Mars Avril Juin Juillet]
[Janvier Mars Avril Juin Juillet]
Copier le contenu d'une Slice
Il est possible de copier le contenu d'une slice source vers une slice cible grâce à la fonction copy(). Cette fonction prend comme premier paramètre la slice cible et comme deuxième paramètre la slice source.
Attention
La fonction copy() copie le contenu d’une tranche source vers une source cible, il est donc important que la slice cible soit de même taille que la slice source afin de copier le contenu total de la cible.
package main
import "fmt"
func main() {
animaux1 := []string{"Lion", "Cheval", "Ours"}
fmt.Println("Contenu du tableau animaux1 :", animaux1)
// création d'une slice cible avec la même taille que la slice source
animaux2 := make([]string, len(animaux1))
// copie du contenu de la slice source vers la slice cible
copy(animaux2, animaux1)
fmt.Println("Contenu du tableau animaux2 :", animaux2)
}
Résultat :
Contenu du tableau animaux1 : [Lion Cheval Ours]
Contenu du tableau animaux2 : [Lion Cheval Ours]
Espace commentaire
Écrire un commentaire
Rejoignez la discussion
Vous devez être connecté pour poster un message.
25 commentaires
N'oubliez pas que les slices partagent le même tableau sous-jacent. Si vous modifiez une sous-slice, ça impacte l'originale.
Assure-toi que tes deux slices ont exactement le même type de données. Go est très rigide sur les types.
J'ai une erreur de compilation avec
copy, type mismatch.Ah, c'est pour ça qu'il faut prévoir la capacité avec
make([]int, 0, capacity).Attention à la réallocation. Si la capacité est dépassée, Go crée un nouveau tableau sous le capot, ça peut coûter cher en perfs.
Est-ce qu'il y a un risque à utiliser
appenddans une boucle for ?Stylé l'astuce du filtrage, c'est beaucoup plus efficace.
Quelqu'un a un exemple pour filtrer une slice en place ?
Je comprends mieux le concept de slice maintenant, c'est beaucoup plus flexible qu'en C.
Oui, si tu supprimes un élément, mets la case libérée à
nilavant de faire leappendpour aider le GC.J'ai un souci avec une slice de pointeurs. Si je supprime, ça peut créer des fuites mémoire ?
La première est
nil, la seconde est allouée mais vide. Privilégie make si tu connais la taille à l'avance.C'est quoi la différence de perf entre
var s []intets := make([]int, 0)?Sympa le tuto. Par contre j'ai toujours du mal avec les index lors de la suppression.
Utilise
appendavec le déballage :Comment on fait pour fusionner deux slices proprement ?
Ok, c'était bien ça. La doc dit que la taille doit être la même, c'est assez strict.
Vérifie la taille de ta destination.
copy()ne redimensionne pas automatiquement, il faut quelen(cible)>=len(source).J'ai testé
copy()mais ma slice cible est restée vide. Quelqu'un voit mon erreur ?Est-ce qu'on peut changer la capacité d'une slice
make([]int, 5)après coup sans créer une nouvelle variable ?Parce que
appendattend des éléments individuels en variadique. Le...permet de déballer ta slice en une liste d'arguments.Merci pour l'article. Par contre, pour la suppression, pourquoi on doit mettre les
...à la fin de la fonctionappend?Oui, c'est normal. Ta slice est
nil. Tu dois utilisermake()ou l'initialiser avec des valeurs pour allouer la mémoire.J'ai essayé de déclarer ma slice avec
var tab []intpuis d'assigner une valeur àtab[0]et ça me sort un panic: runtime error. C'est normal ?