Der Bereich von Go kann über Karten und Slices iterieren, aber ich habe mich gefragt, ob es eine Möglichkeit gibt, über einen Bereich von Zahlen zu iterieren, etwa so:
for i := range [1..10] {
fmt.Println(i)
}
Oder gibt es eine Möglichkeit, den Bereich von Ganzzahlen in Go so darzustellen, wie Ruby es mit der Klasse Range macht ?
Hier ist ein Programm zum Vergleich der beiden bisher vorgeschlagenen Methoden
Kompilieren Sie wie folgt, um eine Demontage zu generieren
Hier ist klar (ich habe die Nicht-Anweisungen aus der Liste entfernt)
Konfiguration
Schleife
Und hier ist with_iter
Konfiguration
Schleife
Sie sehen also, dass die Iter-Lösung erheblich teurer ist, obwohl sie in der Einrichtungsphase vollständig integriert ist. In der Schleifenphase gibt es eine zusätzliche Anweisung in der Schleife, aber es ist nicht so schlimm.
Ich würde die einfache for-Schleife verwenden.
quelle
runtime.makeslice
und die andere nicht - ich brauche keinen Benchmark, um zu wissen, dass das viel langsamer sein wird!runtime.makeslice
ist klug genug, um keinen Speicher zuzuweisen, wenn Sie nach einer Größenzuweisung von Null fragen. Das Obige nennt es jedoch immer noch und laut Ihrem Benchmark dauert es auf meinem Computer 10 ns länger.Es wurde von Mark Mishyn vorgeschlagen, Slice zu verwenden, aber es gibt keinen Grund, ein Array mit
make
und einfor
zurückgegebenes Slice davon zu erstellen , wenn ein über Literal erstelltes Array verwendet werden kann und es kürzer istquelle
for range [5]int{} {
5
hier ein Literal ist und zur Laufzeit nicht ermittelt werden kann.iter ist ein sehr kleines Paket, das nur eine syntantisch andere Möglichkeit bietet, über ganze Zahlen zu iterieren.
Rob Pike (ein Autor von Go) hat es kritisiert :
quelle
iter
verwendeten Version tatsächlich wenige Tastenanschläge darange
unditer
automatisch vervollständigt werden.for
Loops sind keine erstklassigen Unix-Bürger, wie sie unterwegs sind. Außerdem, im Gegensatz zufor
,seq
strömt in der Standardausgabe eine Folge von Zahlen. Ob sie darüber iterieren oder nicht, liegt beim Verbraucher. Obwohl diesfor i in $(seq 1 10); do ... done
in Shell üblich ist, ist es nur eine Möglichkeit, eine for-Schleife zu erstellen, die selbst nur eine Möglichkeit ist, die Ausgabe von zu verbrauchenseq
, wenn auch eine sehr häufige.i in range(10)
genau wiei := 0; i < 10; i++
.Hier ist ein Benchmark zum Vergleichen einer Go-
for
Anweisung mit einer ForClause- und einer Go-range
Anweisung unter Verwendung desiter
Pakets.iter_test.go
Ausgabe:
quelle
Obwohl ich Ihre Besorgnis über das Fehlen dieser Sprachfunktion bedauere, möchten Sie wahrscheinlich nur eine normale
for
Schleife verwenden. Und Sie werden wahrscheinlich mehr damit einverstanden sein, als Sie denken, wenn Sie mehr Go-Code schreiben.Ich habe dieses Iter-Paket geschrieben, das von einer einfachen, idiomatischen
for
Schleife unterstützt wird, die Werte über a zurückgibtchan int
, um das Design in https://github.com/bradfitz/iter zu verbessern, auf das hingewiesen wurde Caching- und Leistungsprobleme sowie eine clevere, aber seltsame und nicht intuitive Implementierung. Meine eigene Version funktioniert genauso:Das Benchmarking ergab jedoch, dass die Verwendung eines Kanals eine sehr teure Option war. Der Vergleich der 3 Methoden, die
iter_test.go
in meinem Paket mit ausgeführt werden könnenquantifiziert, wie schlecht seine Leistung ist
Dabei zeigt dieser Benchmark auch, wie
bradfitz
schlecht die Lösung im Vergleich zur integriertenfor
Klausel für eine Schleifengröße von ist10
.Kurz gesagt, es scheint bisher keine Möglichkeit zu geben, die Leistung der integrierten
for
Klausel zu duplizieren und gleichzeitig eine einfache Syntax für bereitzustellen[0,n)
wie in Python und Ruby bereitzustellen.Das ist eine Schande, denn für das Go-Team wäre es wahrscheinlich einfach, dem Compiler eine einfache Regel hinzuzufügen, um eine Zeile wie zu ändern
auf den gleichen Maschinencode wie
for i := 0; i < 10; i++
.Um fair zu sein, habe ich nach dem Schreiben meines eigenen
iter.N
Programms (aber vor dem Benchmarking) ein kürzlich geschriebenes Programm durchgesehen, um alle Stellen zu sehen, an denen ich es verwenden konnte. Es waren eigentlich nicht viele. Es gab nur eine Stelle in einem nicht wichtigen Abschnitt meines Codes, an der ich ohne die vollständigere Standardklausel auskommen konntefor
.Während es so aussieht, als wäre dies im Prinzip eine große Enttäuschung für die Sprache, werden Sie - wie ich - feststellen, dass Sie es in der Praxis eigentlich nicht wirklich brauchen. Wie Rob Pike für Generika bekannt ist, verpassen Sie diese Funktion möglicherweise nicht so sehr, wie Sie denken.
quelle
Wenn Sie nur über einen Bereich ohne Verwendung von und Indizes oder irgendetwas anderem iterieren möchten, hat dieses Codebeispiel für mich gut funktioniert. Keine zusätzliche Erklärung erforderlich, nein
_
. Ich habe die Leistung jedoch nicht überprüft.PS Der allererste Tag in GoLang. Bitte kritisieren Sie, wenn es ein falscher Ansatz ist.
quelle
non-constant array bound
Mich anwerfen .Sie können auch github.com/wushilin/stream besuchen
Es ist ein fauler Stream wie das Konzept von java.util.stream.
Hoffe das hilft
quelle
quelle
Ich habe in Golang ein Paket geschrieben, das die Bereichsfunktion von Python nachahmt:
Paket https://github.com/thedevsaddam/iter
quelle