英文:
Is ranging over an array a bad way to write a simple loop?
问题
有时候,我厌倦了为一个固定次数的循环编写 ForClause for i := 0; i < 7; i++ {
,而且循环迭代器并不需要。有时候我希望能够使用 range 和一个整数,比如 for range 7 {
,但这是无效的。我发现可以使用 for range [7]int{} {
。
这看起来没问题:
package kata
import (
"runtime"
"testing"
)
const times = 100_000
func BenchmarkLoop(b *testing.B) {
b.Run("For", func(b *testing.B) {
for j := 0; j < b.N; j++ {
for i := 0; i < times; i++ {
runtime.Gosched()
}
}
})
b.Run("Range", func(b *testing.B) {
for j := 0; j < b.N; j++ {
for range [times]int{} {
runtime.Gosched()
}
}
})
}
% go test -bench=. -benchmem
goos: darwin
goarch: amd64
pkg: github.com/brackendawson/kata
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkLoop/For-12 157 8963540 ns/op 0 B/op 0 allocs/op
BenchmarkLoop/Range-12 162 7651102 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/brackendawson/kata 4.695s
这样安全吗?我是不是在无意中节省了4个按键?我感觉很不舒服。
英文:
I sometimes tire of writing the ForClause for i := 0; i < 7; i++ {
loop for a constant number of loops where the loop iterator isn't needed. I sometimes wish I could use range and an integer like for range 7 {
but that is invalid. I have found you can use for range [7]int{} {
.
Which seems fine:
package kata
import (
"runtime"
"testing"
)
const times = 100_000
func BenchmarkLoop(b *testing.B) {
b.Run("For", func(b *testing.B) {
for j := 0; j < b.N; j++ {
for i := 0; i < times; i++ {
runtime.Gosched()
}
}
})
b.Run("Range", func(b *testing.B) {
for j := 0; j < b.N; j++ {
for range [times]int{} {
runtime.Gosched()
}
}
})
}
% go test -bench=. -benchmem
goos: darwin
goarch: amd64
pkg: github.com/brackendawson/kata
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkLoop/For-12 157 8963540 ns/op 0 B/op 0 allocs/op
BenchmarkLoop/Range-12 162 7651102 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/brackendawson/kata 4.695s
Is this safe? Am I pointlessly saving 4 keystrokes? I feel dirty.
答案1
得分: 6
虽然安全,但我认为这不是惯用的写法。在Go语言中,应该追求尽可能简单的代码。原始的for
循环对于读者来说更清晰,代码应该优化为可读性,而不是为了节省按键次数(如果要节省按键次数,可以考虑配置你的编辑器/IDE)。
如果你坚持要缩短代码,至少可以使用像https://pkg.go.dev/github.com/bradfitz/iter这样的库(或重新实现它-这很简单),这样你就可以写成:
for i := range iter.N(10) {
// ....
}
这比显式地使用数组更短,更易读,尽管我仍然认为它比普通的for
循环不易读。
总之,最好不要这样做
英文:
While safe, I would argue this is not idiomatic. In Go, strive for the simplest code possible. The original for
loop is much clearer for readers, and code should be optimized for reading, not for saving keystrokes (for saving keystrokes, consider configuring your editor/IDE instead?)
If you insist on making it shorter, at least use something like https://pkg.go.dev/github.com/bradfitz/iter (or reimplement it - it's trivial), to be able to write:
for i := range iter.N(10) {
// ....
}
This is shorter and is more readable than having that array there explicitly, though I'd still argue it's less readable than a vanilla for
loop.
To conclude, just don't
答案2
得分: -1
个人而言,我偶尔会使用这个成语,尽管我使用的是struct
而不是range
:
package main
func main() {
for range [9]struct{}{} {
println("嘿,伙计")
}
}
因为空结构体不占用任何字节。我认为这与Python的range
[1]并没有太大的区别:
for _ in range(9):
print('嘿,伙计')
英文:
Personally I do use this idiom now and then, although I use a struct
instead:
package main
func main() {
for range [9]struct{}{} {
println("hey homie")
}
}
as empty struct takes zero bytes. I don't think it's that different from Python range
[1]:
for _ in range(9):
print('hey homie')
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论