在一个数组上进行范围循环是一种不好的编写简单循环的方式吗?

huangapple go评论82阅读模式
英文:

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 &lt; 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 (
	&quot;runtime&quot;
	&quot;testing&quot;
)

const times = 100_000

func BenchmarkLoop(b *testing.B) {
	b.Run(&quot;For&quot;, func(b *testing.B) {
		for j := 0; j &lt; b.N; j++ {
			for i := 0; i &lt; times; i++ {
				runtime.Gosched()
			}
		}
	})
	b.Run(&quot;Range&quot;, func(b *testing.B) {
		for j := 0; j &lt; 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('嘿,伙计')
  1. https://docs.python.org/library/functions.html#func-range
英文:

Personally I do use this idiom now and then, although I use a struct instead:

package main

func main() {
   for range [9]struct{}{} {
      println(&quot;hey homie&quot;)
   }
}

as empty struct takes zero bytes. I don't think it's that different from Python range [1]:

for _ in range(9):
   print(&#39;hey homie&#39;)
  1. https://docs.python.org/library/functions.html#func-range

huangapple
  • 本文由 发表于 2021年6月17日 05:29:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/68010243.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定