La plage de Go peut itérer sur des cartes et des tranches, mais je me demandais s'il existe un moyen d'itérer sur une plage de nombres, quelque chose comme ceci:
for i := range [1..10] {
fmt.Println(i)
}
Ou y a-t-il un moyen de représenter une plage d'entiers dans Go comme le fait Ruby avec la classe Range ?
Voici un programme pour comparer les deux méthodes suggérées jusqu'à présent
Compilez comme ça pour générer le désassemblage
Voici clair (j'ai supprimé les instructions non de la liste)
installer
boucle
Et voici avec_iter
installer
boucle
Ainsi, vous pouvez voir que la solution iter est considérablement plus chère même si elle est entièrement intégrée dans la phase de configuration. Dans la phase de boucle, il y a une instruction supplémentaire dans la boucle, mais ce n'est pas trop mal.
J'utiliserais la simple boucle for.
la source
runtime.makeslice
et l'autre pas - je n'ai pas besoin d'un benchmark pour savoir que ça va être beaucoup plus lent!runtime.makeslice
est suffisamment intelligent pour ne pas allouer de mémoire si vous demandez une allocation de taille nulle. Cependant, ce qui précède l'appelle toujours, et selon votre benchmark, cela prend 10 nS de plus sur ma machine.Il a été suggéré par Mark Mishyn d'utiliser slice, mais il n'y a aucune raison de créer un tableau avec
make
et de l'utiliser dans lafor
tranche renvoyée de celui-ci lorsqu'un tableau créé via un littéral peut être utilisé et qu'il est plus courtla source
for range [5]int{} {
5
s'agit d'un littéral et ne peut pas être déterminé au moment de l'exécution.iter est un tout petit package qui fournit juste une manière syntantiquement différente d'itérer sur des entiers.
Rob Pike (un auteur de Go) l' a critiqué :
la source
iter
version utilise en fait moins de frappes, carrange
etiter
se complétera automatiquement.for
boucles ne sont pas des citoyens de premier ordre d'Unix comme elles le sont. En outre, à la différencefor
, lesseq
flux de sortie standard d' une séquence de nombres. Il appartient au consommateur de décider ou non de les parcourir. Bien que cefor i in $(seq 1 10); do ... done
soit courant dans Shell, ce n'est qu'une façon de faire une boucle for, qui n'est en soi qu'une façon de consommer la sortie deseq
, bien que très courante.i in range(10)
exactement commei := 0; i < 10; i++
.Voici un benchmark pour comparer une
for
instruction Go avec une ForClause et unerange
instruction Go à l'aide duiter
package.iter_test.go
Production:
la source
Bien que je compatisse avec votre inquiétude concernant l'absence de cette fonctionnalité de langue, vous allez probablement vouloir simplement utiliser un
for
boucle . Et vous serez probablement plus d'accord avec cela que vous ne le pensez en écrivant plus de code Go.J'ai écrit ce package iter - qui est soutenu par une simple
for
boucle idiomatique qui renvoie des valeurs sur achan int
- dans le but d'améliorer la conception trouvée dans https://github.com/bradfitz/iter , qui a été signalée comme ayant des problèmes de mise en cache et de performances, ainsi qu'une implémentation intelligente, mais étrange et peu intuitive. Ma propre version fonctionne de la même manière:Cependant, l'analyse comparative a révélé que l'utilisation d'un canal était une option très coûteuse. La comparaison des 3 méthodes, qui peuvent être exécutées à partir
iter_test.go
de mon package en utilisantquantifie à quel point ses performances sont médiocres
Dans le processus, ce test de
bradfitz
performance montre également comment la solution sous-performante par rapport à lafor
clause intégrée pour une taille de boucle de10
.En bref, il ne semble y avoir aucun moyen découvert jusqu'à présent de dupliquer les performances de la
for
clause intégrée tout en fournissant une syntaxe simple pour[0,n)
comme celle trouvée dans Python et Ruby.Ce qui est dommage car il serait probablement facile pour l'équipe Go d'ajouter une règle simple au compilateur pour changer une ligne comme
au même code machine que
for i := 0; i < 10; i++
.Cependant, pour être honnête, après avoir écrit le mien
iter.N
(mais avant de le comparer), je suis revenu sur un programme récemment écrit pour voir tous les endroits où je pouvais l'utiliser. Il n'y en avait pas beaucoup. Il n'y avait qu'un seul endroit, dans une section non vitale de mon code, où je pourrais me débrouiller sans lafor
clause par défaut plus complète .Donc, même si cela peut sembler être une énorme déception pour la langue en principe, vous pouvez constater - comme je l'ai fait - que vous n'en avez pas vraiment besoin dans la pratique. Comme Rob Pike est connu pour le dire pour les génériques, vous ne manquerez peut-être pas cette fonctionnalité autant que vous le pensez.
la source
Si vous souhaitez simplement itérer sur une plage sans utiliser d'index et ou quoi que ce soit d'autre, cet exemple de code a très bien fonctionné pour moi. Aucune déclaration supplémentaire nécessaire, non
_
. Je n'ai pas vérifié les performances, cependant.PS Le tout premier jour à GoLang. S'il vous plaît, faites une critique si c'est une mauvaise approche.
la source
non-constant array bound
sur moi.Vous pouvez également consulter github.com/wushilin/stream
C'est un flux paresseux comme le concept de java.util.stream.
J'espère que cela t'aides
la source
la source
J'ai écrit un package dans Golang qui imite la fonction range de Python:
Paquet https://github.com/thedevsaddam/iter
la source