Go的范围可以在地图和切片上迭代,但我想知道是否有一种方法可以在数字范围上迭代,就像这样:
for i := range [1..10] {
fmt.Println(i)
}
或者在Go中是否有一种方法来表示整数的范围,就像Ruby对range类所做的那样?
Go的范围可以在地图和切片上迭代,但我想知道是否有一种方法可以在数字范围上迭代,就像这样:
for i := range [1..10] {
fmt.Println(i)
}
或者在Go中是否有一种方法来表示整数的范围,就像Ruby对range类所做的那样?
当前回答
如果你只是想在一个w/o范围内使用和索引或其他东西进行迭代,这个代码样本对我来说很好。不需要额外的声明,没有_。不过,还没有检查性能。
for range [N]int{} {
// Body...
}
附注:在戈朗的第一天。如果这是一种错误的方法,请进行批评。
其他回答
你也可以退房 github.com/wushilin/stream
它是一个类似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()
希望这能有所帮助
下面是一个程序来比较目前建议的两种方法
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()
}
像这样编译以生成反汇编
go build -gcflags -S iter.go
这里是简单的(我已经从清单中删除了非指令)
设置
0035 (/home/ncw/Go/iter.go:14) MOVQ $0,AX
0036 (/home/ncw/Go/iter.go:14) JMP ,38
loop
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 ,
这里是with_iter
设置
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
loop
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 ,
所以你可以看到iter解决方案是相当昂贵的,即使它是完全内联在设置阶段。在循环阶段,循环中有一个额外的指令,但这并不太糟糕。
我会使用简单的for循环。
如果你只是想在一个w/o范围内使用和索引或其他东西进行迭代,这个代码样本对我来说很好。不需要额外的声明,没有_。不过,还没有检查性能。
for range [N]int{} {
// Body...
}
附注:在戈朗的第一天。如果这是一种错误的方法,请进行批评。
问题不在于范围,而在于如何计算切片的末端。 对于固定的数字10,简单的for循环是可以的,但是对于像bfl.Size()这样的计算大小,你在每次迭代时都得到一个函数调用。大于int32的简单范围会有所帮助,因为这只计算bfl.Size()一次。
type BFLT PerfServer
func (this *BFLT) Call() {
bfl := MqBufferLCreateTLS(0)
for this.ReadItemExists() {
bfl.AppendU(this.ReadU())
}
this.SendSTART()
// size := bfl.Size()
for i := int32(0); i < bfl.Size() /* size */; i++ {
this.SendU(bfl.IndexGet(i))
}
this.SendRETURN()
}
Go中的惯用方法是这样写一个for循环。
for i := 1; i <= 10; i++ {
fmt.Println(i)
}
在范围上肯定有优势,它们也被用于许多其他语言中,但Go的设计原则是,只有在收益显著超过成本(包括使语言更大的成本)时才引入抽象。理性的人不同意范围的成本和收益,但这个答案是我试图描述我认为的惯用围棋是什么。