web-dev-qa-db-fra.com

Comment implémenter des tableaux redimensionnables dans Go

Je viens d'un contexte C++ et je suis habitué à utiliser la classe std::vector pour des choses comme celle-ci . Supposons que je veuille un tableau dynamique comprenant:

type a struct {
    b int
    c string
}

Quel est le moyen standard de le faire?

Un extrait serait très utile  

48
user181351

Utilisez la fonction append()

Exemple:

type mytype struct {
  a, b int
}

func main() {
  a := []mytype{mytype{1, 2}, mytype{3, 4}}
  a = append(a, mytype{5, 6})
}

Reportez-vous à spec pour plus d'informations sur append.

50
cthom06

Une tranche de lancement contient trois éléments: les données, la longueur et la capacité.

s := make([]int, 0, 10)

La variable s est une tranche d'ints de longueur 0 et de capacité 10. Les fonctions intégrées len () et cap () vous permettent d'obtenir la longueur et la capacité d'une tranche:

len(s) == 0
cap(s) == 10

Pour augmenter la longueur d'une tranche, il suffit de découper à nouveau:

s = s[0:5]
// len(s) == 5
// cap(s) == 10

Pour diminuer la longueur, vous pouvez prendre une sous-tranche:

s = s[0:1]
// len(s) == 1

Il existe des moyens plus courts d’appeler make ():

a := make([]int, 10) 
// len(a) == cap(a) == 10

b := make([]int)
// len(b) == cap(b) == 0

C'est bien beau, mais si vous deviez augmenter la longueur d'une tranche au-delà de sa capacité? Pour ce faire, vous devez allouer une nouvelle tranche et copier le contenu de l'ancienne tranche dans la nouvelle. (La fonction "copier" est une autre fonction intégrée.)

t := make([]int, len(s), 20)
copy(t, s)

Le document Effective Go va un peu plus loin dans cet exemple, en implémentant une fonction Append qui ajoute une tranche à une autre et la redimensionne si nécessaire.

Les tranches sont soutenues par des tableaux; lorsque vous faites () une tranche d'une capacité spécifique, un tableau de cette capacité est alloué en arrière-plan. La tranche devient en réalité un "pointeur intelligent" vers ce tableau. Si vous transmettez cette tranche (ou une sous-tranche de cette tranche) à une autre fonction, elle est transmise en tant que pointeur sur le même tableau. Cela rend les sous-tranches très économiques à créer: c'est l'allocation de la matrice de sauvegarde qui coûte cher.

La bibliothèque standard Go comprend un certain nombre de packages de conteneurs, vectoriels par exemple, qui évitent de gérer manuellement les tranches. Utilisez des tranches pour plus de rapidité et des classes de conteneurs plus élaborées pour plus de commodité. (Cela dit, j'utilise toujours des tranches pour la plupart des choses.)

Vous vous demandez peut-être pourquoi vous avez besoin de tous ces problèmes. Après tout, beaucoup de langages fournissent des tableaux redimensionnés dynamiquement sous forme de primitives. La raison en est liée à la philosophie de Go. Les concepteurs de langage ne prétendent pas savoir quelle est la politique d'allocation appropriée pour votre programme; au lieu de cela, ils vous donnent les outils dont vous avez besoin pour créer vos propres structures de données.

54
Andrew Gerrand

La manière idiomatique de faire cela a changé ..___. L'ajout de la fonction append () intégrée signifie que vous pouvez étendre une tranche de la façon suivante:

type a struct {
    b int
    c string
}

func main(){
    var mySlice []a
    mySlice = append(mySlice,a{5,"pizza"})
}

Append () ajoutera l'élément donné à la tranche s'il y a de la place ou prolongera la tranche si elle n'est pas assez grande.

Plus d'informations sur append () is here http://golang.org/doc/go_spec.html#Appending_and_copying_slices

17
Jessta

vous pouvez aussi vous débrouiller avec une part. qui est un tableau qui connaît sa longueur actuelle. Et peut avoir une longueur de courant et une capacité maximale distinctes. Notez que les valeurs transmises pour la taille et la capacité initiales ne doivent pas nécessairement être des constantes. Vous pouvez donc créer une fonction qui génère et renvoie des tranches de différentes longueurs en fonction de ses paramètres.

L'aspect positif est qu'un slice [] Int peut simplement être indexé comme un tableau et retournera des ints lorsqu'il est utilisé de cette manière.

L'inconvénient est qu'il ne croîtra pas automatiquement en excès par rapport à la capacité indiquée. Effective Go a un exemple de la façon dont vous vous y prendriez pour gérer la réaffectation. 

le code serait

type mytype struct {
   a, b int
}




func main() {

  sl := make([]mytype, 10, 50) //slice of 10 items, max capacity 50 these do not have to be constant expressions.
  sl[0] = mytype{1,2}
   //...
  for i, value := range sl {
  // ... do stuff with value
  }
}
1
user414731

Bonjour, nous pouvons le faire simplement de deux manières

type mytype struct {
  a, b int
}

Juste faire comme ça

  1. Sans append

__

a := []mytype{mytype{1, 2}, mytype{3, 4}, mytype{4, 5}}
  1. Avec append

__

a:=  append([]mytype{}, mytype{1, 2}, mytype{3, 4}, mytype{4, 5})

Ajoutez autant que vous voulez. Le premier est un moyen facile de le faire. J'espère que ceci vous aidera.

0
amku91