Is there a way to iterate over a series of integers in the Golang?

Golang range can iterate over maps and slices, but I was wondering if there is a way to iterate over a range of numbers, something like this

for i := range [1..10] { fmt.Println(i) } 

or is there a way to represent a range of integers in Go, how does ruby ​​do it?

+143
go
Feb 22 '14 at 5:39
source share
10 answers

You can and should just write a for loop. Simple, obvious code is the Go way.

 for i := 1; i <= 10; i++ { fmt.Println(i) } 
+193
Feb 22 '14 at 7:15
source share

Here is a program to compare the two methods proposed so far

 import ( "fmt" "github.com/bradfitz/iter" ) func p(i int) { fmt.Println(i) } func plain() { for i := 0; i < 10; i++ { p(i) } } func with_iter() { for i := range iter.N(10) { p(i) } } func main() { plain() with_iter() } 

Compile to create a disassembly

 go build -gcflags -S iter.go 

Here is a simple one (I removed the exception from the instructions)

Customization

 0035 (/home/ncw/Go/iter.go:14) MOVQ $0,AX 0036 (/home/ncw/Go/iter.go:14) JMP ,38 

hinges

 0037 (/home/ncw/Go/iter.go:14) INCQ ,AX 0038 (/home/ncw/Go/iter.go:14) CMPQ AX,$10 0039 (/home/ncw/Go/iter.go:14) JGE $0,45 0040 (/home/ncw/Go/iter.go:15) MOVQ AX,i+-8(SP) 0041 (/home/ncw/Go/iter.go:15) MOVQ AX,(SP) 0042 (/home/ncw/Go/iter.go:15) CALL ,p+0(SB) 0043 (/home/ncw/Go/iter.go:15) MOVQ i+-8(SP),AX 0044 (/home/ncw/Go/iter.go:14) JMP ,37 0045 (/home/ncw/Go/iter.go:17) RET , 

And here s_name

Customization

 0052 (/home/ncw/Go/iter.go:20) MOVQ $10,AX 0053 (/home/ncw/Go/iter.go:20) MOVQ $0,~r0+-24(SP) 0054 (/home/ncw/Go/iter.go:20) MOVQ $0,~r0+-16(SP) 0055 (/home/ncw/Go/iter.go:20) MOVQ $0,~r0+-8(SP) 0056 (/home/ncw/Go/iter.go:20) MOVQ $type.[]struct {}+0(SB),(SP) 0057 (/home/ncw/Go/iter.go:20) MOVQ AX,8(SP) 0058 (/home/ncw/Go/iter.go:20) MOVQ AX,16(SP) 0059 (/home/ncw/Go/iter.go:20) PCDATA $0,$48 0060 (/home/ncw/Go/iter.go:20) CALL ,runtime.makeslice+0(SB) 0061 (/home/ncw/Go/iter.go:20) PCDATA $0,$-1 0062 (/home/ncw/Go/iter.go:20) MOVQ 24(SP),DX 0063 (/home/ncw/Go/iter.go:20) MOVQ 32(SP),CX 0064 (/home/ncw/Go/iter.go:20) MOVQ 40(SP),AX 0065 (/home/ncw/Go/iter.go:20) MOVQ DX,~r0+-24(SP) 0066 (/home/ncw/Go/iter.go:20) MOVQ CX,~r0+-16(SP) 0067 (/home/ncw/Go/iter.go:20) MOVQ AX,~r0+-8(SP) 0068 (/home/ncw/Go/iter.go:20) MOVQ $0,AX 0069 (/home/ncw/Go/iter.go:20) LEAQ ~r0+-24(SP),BX 0070 (/home/ncw/Go/iter.go:20) MOVQ 8(BX),BP 0071 (/home/ncw/Go/iter.go:20) MOVQ BP,autotmp_0006+-32(SP) 0072 (/home/ncw/Go/iter.go:20) JMP ,74 

hinges

 0073 (/home/ncw/Go/iter.go:20) INCQ ,AX 0074 (/home/ncw/Go/iter.go:20) MOVQ autotmp_0006+-32(SP),BP 0075 (/home/ncw/Go/iter.go:20) CMPQ AX,BP 0076 (/home/ncw/Go/iter.go:20) JGE $0,82 0077 (/home/ncw/Go/iter.go:20) MOVQ AX,autotmp_0005+-40(SP) 0078 (/home/ncw/Go/iter.go:21) MOVQ AX,(SP) 0079 (/home/ncw/Go/iter.go:21) CALL ,p+0(SB) 0080 (/home/ncw/Go/iter.go:21) MOVQ autotmp_0005+-40(SP),AX 0081 (/home/ncw/Go/iter.go:20) JMP ,73 0082 (/home/ncw/Go/iter.go:23) RET , 

So, you can see that the iter solution is much more expensive, although it is fully included in the installation phase. There is additional instruction in the loop phase in the loop, but this is not so bad.

I would use a simple loop.

+35
Feb 22 '14 at 8:50
source share

Mark Mishin was invited to use a slice, but there is no reason to create an array with make and use it in the for fragment returned when an array created through a literal can be used shorter

 for i := range [5]int{} { fmt.Println(i) } 
+24
Dec 07 '17 at 21:34 on
source share

iter is a very small package that just provides a syntactically great way to iterate over integers.

 for i := range iter.N(4) { fmt.Println(i) } 

Rob Pike (author of Go) criticized him :

It seems that almost every time someone comes up with a way to avoid doing something like a for loop in an idiomatic way, because it feels too long or cumbersome, the result is almost always more keystrokes than what is supposedly shorter. [...] What leaves out all the crazy overhead, these "improvements" bring.

+14
Feb 22 '14 at 5:44
source share

Here is an example of comparing the Go for statement with the ForClause statement and Go range using the iter package.

iter_test.go

 package main import ( "testing" "github.com/bradfitz/iter" ) const loops = 1e6 func BenchmarkForClause(b *testing.B) { b.ReportAllocs() j := 0 for i := 0; i < bN; i++ { for j = 0; j < loops; j++ { j = j } } _ = j } func BenchmarkRangeIter(b *testing.B) { b.ReportAllocs() j := 0 for i := 0; i < bN; i++ { for j = range iter.N(loops) { j = j } } _ = j } // It does not cause any allocations. func N(n int) []struct{} { return make([]struct{}, n) } func BenchmarkIterAllocs(b *testing.B) { b.ReportAllocs() var n []struct{} for i := 0; i < bN; i++ { n = iter.N(loops) } _ = n } 

Output:

 $ go test -bench=. -run=. testing: warning: no tests to run PASS BenchmarkForClause 2000 1260356 ns/op 0 B/op 0 allocs/op BenchmarkRangeIter 2000 1257312 ns/op 0 B/op 0 allocs/op BenchmarkIterAllocs 20000000 82.2 ns/op 0 B/op 0 allocs/op ok so/test 7.026s $ 
+8
Feb 22 '14 at 18:23
source share

While I sympathize with your concern about the lack of this language feature, you probably just want to use the regular for loop. And you'll probably be alright with this than you think when you write more Go code.

I wrote this iter package - which is supported by a simple, idiomatic for loop that returns values ​​over chan int - in an attempt to improve the design found at https://github.com/bradfitz/iter , which indicated that there were caching and performance issues, as well as a smart but weird and non-intuitive implementation. My own version works the same way:

 package main import ( "fmt" "github.com/drgrib/iter" ) func main() { for i := range iter.N(10) { fmt.Println(i) } } 

However, a comparative analysis showed that using the channel was a very expensive option. Comparing the three methods that can be run from iter_test.go in my package using

 go test -bench=. -run=. 

determines how bad its performance

 BenchmarkForMany-4 5000 329956 ns/op 0 B/op 0 allocs/op BenchmarkDrgribIterMany-4 5 229904527 ns/op 195 B/op 1 allocs/op BenchmarkBradfitzIterMany-4 5000 337952 ns/op 0 B/op 0 allocs/op BenchmarkFor10-4 500000000 3.27 ns/op 0 B/op 0 allocs/op BenchmarkDrgribIter10-4 500000 2907 ns/op 96 B/op 1 allocs/op BenchmarkBradfitzIter10-4 100000000 12.1 ns/op 0 B/op 0 allocs/op 

In this process, this test also shows how the bradfitz solution works worse than the built-in for clause for loop size 10 .

In short, it has not yet been able to detect duplicate performance of the built-in for clause, providing simple syntax for [0,n) , like the one found in Python and Ruby.

What a shame, because the Go command can easily add a simple rule to the compiler to change a line like

 for i := range 10 { fmt.Println(i) } 

to the same machine code as for i := 0; i < 10; i++ for i := 0; i < 10; i++ for i := 0; i < 10; i++ .

However, to be honest, after writing my own iter.N (but before benchmarking it), I went back through a recently written program to see all the places where I could use it. In fact, there were few of them. There was only one place in the non-critical section of my code where I could do without a more complete default for clause.

So, although it might seem like a huge disappointment for the language in principle, you can find - like me - that you really don't need it. As you know, Rob Pike talks about generics, you may not miss this feature as much as you think.

+4
Apr 03 '17 at 18:54 on
source share

There is an ugly solution, but it is a bit closer to Ruby for i in 0..N or Python for i in range(N)

 for i := range make([]int, 5){ fmt.Println(i) } 

So yes, you should use a for i:=0; i<N; i++ {} loop for i:=0; i<N; i++ {} for i:=0; i<N; i++ {} for i:=0; i<N; i++ {} or iter .

+1
Aug 15 '17 at 16:44
source share
 package main import "fmt" func main() { nums := []int{2, 3, 4} for _, num := range nums { fmt.Println(num, sum) } } 
+1
Jul 26 '18 at 2:49
source share

If you want to just iterate over a range without using indexes or anything else, this code example worked just fine for me. No additional declaration is required, no _ . However, I did not check the performance.

 for range [N]int{} { // Body... } 

PS The very first day at GoLang. Please criticize if this is the wrong approach.

+1
Jul 30 '19 at 3:51
source share

You can also check out github.com/wushilin/stream

This is a lazy stream, similar to the concept of java.util.stream.

 // It doesn't really allocate the 10 elements. stream1 := stream.Range(0, 10) // Print each element. stream1.Each(print) // Add 3 to each element, but it is a lazy add. // You only add when consume the stream stream2 := stream1.Map(func(i int) int { return i + 3 }) // Well, this consumes the stream => return sum of stream2. stream2.Reduce(func(i, j int) int { return i + j }) // Create stream with 5 elements stream3 := stream.Of(1, 2, 3, 4, 5) // Create stream from array stream4 := stream.FromArray(arrayInput) // Filter stream3, keep only elements that is bigger than 2, // and return the Sum, which is 12 stream3.Filter(func(i int) bool { return i > 2 }).Sum() 

Hope this helps

0
Oct 02 '15 at 6:50
source share



All Articles