Zakres Go może iterować po mapach i wycinkach, ale zastanawiałem się, czy istnieje sposób na iterację w zakresie liczb, coś takiego:
for i := range [1..10] {
fmt.Println(i)
}
A może istnieje sposób na przedstawienie zakresu liczb całkowitych w Go, tak jak robi to Ruby z klasą Range ?
Oto program do porównania dwóch sugerowanych do tej pory sposobów
Skompiluj w ten sposób, aby wygenerować demontaż
Oto proste (usunąłem nie instrukcje z aukcji)
Ustawiać
pętla
A oto with_iter
Ustawiać
pętla
Możesz więc zobaczyć, że rozwiązanie iterowe jest znacznie droższe, mimo że jest w pełni wbudowane w fazie konfiguracji. W fazie pętli w pętli znajduje się dodatkowa instrukcja, ale nie jest tak źle.
Użyłbym prostej pętli for.
źródło
runtime.makeslice
a drugie nie - nie potrzebuję testu porównawczego, aby wiedzieć, że będzie dużo wolniej!runtime.makeslice
jest na tyle sprytne, aby nie przydzielać żadnej pamięci, jeśli poprosisz o alokację zerowego rozmiaru. Jednak powyższe nadal to nazywa i według twojego testu porównawczego zajmuje to 10 nS dłużej na moim komputerze.Mark Mishyn zasugerował użycie plasterka, ale nie ma powodu, aby tworzyć tablicę z
make
i używać wfor
zwracanym plastrze, gdy można użyć tablicy utworzonej za pomocą literału i jest ona krótszaźródło
for range [5]int{} {
5
jest to literał i nie można go określić w czasie wykonywania.iter to bardzo mały pakiet, który po prostu zapewnia syntantycznie inny sposób iteracji po liczbach całkowitych.
Rob Pike (autor Go) skrytykował to :
źródło
iter
wersja faktycznie wykorzystuje mniej naciśnięć klawiszy, ponieważrange
iiter
będzie się autouzupełnianie.for
pętle nie są obywatelami Uniksa pierwszej klasy, tak jak są w ruchu. Poza tym, w przeciwieństwie dofor
,seq
strumienie mocy standardowej sekwencji liczb. Od konsumenta zależy, czy będzie je powtarzał. Chociażfor i in $(seq 1 10); do ... done
jest to powszechne w Shell, jest to tylko jeden sposób na wykonanie pętli for, która sama w sobie jest tylko jednym ze sposobów wykorzystania danych wyjściowychseq
, aczkolwiek bardzo powszechnym.i in range(10)
dokładnie tak samoi := 0; i < 10; i++
.Oto punkt odniesienia do porównania
for
instrukcji Go z instrukcją ForClause i Gorange
przy użyciuiter
pakietu.iter_test.go
Wynik:
źródło
Chociaż współczuję ci z powodu braku tej funkcji języka, prawdopodobnie będziesz chciał użyć zwykłej
for
pętli. I prawdopodobnie będziesz z tym bardziej w porządku, niż myślisz, pisząc więcej kodu w Go.Napisałem ten pakiet iterowy - który jest wspierany przez prostą, idiomatyczną
for
pętlę, która zwraca wartości ponad achan int
- w celu ulepszenia projektu znalezionego na https://github.com/bradfitz/iter , który, jak wskazano, ma problemy z buforowaniem i wydajnością, a także sprytna, ale dziwna i nieintuicyjna implementacja. Moja własna wersja działa w ten sam sposób:Jednak analiza porównawcza ujawniła, że korzystanie z kanału było bardzo kosztowną opcją. Porównanie 3 metod, które można uruchomić
iter_test.go
w moim pakiecie przy użyciuokreśla ilościowo, jak słaba jest jego wydajność
W tym procesie ten test porównawczy pokazuje również, w jaki sposób
bradfitz
rozwiązanie ma gorsze wyniki w porównaniu z wbudowanąfor
klauzulą dla pętli o rozmiarze10
.Krótko mówiąc, wydaje się, że do tej pory nie odkryto żadnego sposobu na zduplikowanie wydajności wbudowanej
for
klauzuli, zapewniając jednocześnie prostą składnię[0,n)
podobną do tej, którą można znaleźć w Pythonie i Ruby.Szkoda, ponieważ prawdopodobnie zespołowi Go byłoby łatwo dodać prostą regułę do kompilatora, aby zmienić wiersz, taki jak
do tego samego kodu maszynowego co
for i := 0; i < 10; i++
.Jednak, żeby być uczciwym, po napisaniu własnego
iter.N
(ale przed testem porównawczym) wróciłem do niedawno napisanego programu, aby zobaczyć wszystkie miejsca, w których mogłem go użyć. Właściwie nie było ich wiele. Było tylko jedno miejsce w nieistotnej sekcji mojego kodu, w którym mogłem obejść się bez bardziej kompletnej, domyślnejfor
klauzuli.Więc chociaż może to wyglądać na ogromne rozczarowanie dla języka w zasadzie, może się okazać - tak jak ja - że tak naprawdę nie potrzebujesz go w praktyce. Tak jak Rob Pike mówi o produktach generycznych, możesz nie przegapić tej funkcji tak bardzo, jak myślisz.
źródło
Jeśli chcesz po prostu iterować w zakresie bez użycia i indeksów lub czegokolwiek innego, ten przykład kodu działał dobrze dla mnie. Nie potrzeba dodatkowej deklaracji, nie
_
. Nie sprawdzałem jednak wydajności.PS Pierwszy dzień w GoLang. Proszę, krytykujcie, jeśli jest to złe podejście.
źródło
non-constant array bound
we mnie.Możesz również sprawdzić github.com/wushilin/stream
Jest to leniwy strumień podobny do koncepcji java.util.stream.
Mam nadzieję że to pomoże
źródło
źródło
Napisałem pakiet w języku Golang, który naśladuje funkcję zakresu Pythona:
Pakiet https://github.com/thedevsaddam/iter
źródło