在Go语言中实现无需分配内存的循环。

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

Loop without allocation in Go

问题

在Go语言中,如果我想要重复某个操作500次,但是我不需要使用索引,有没有一种方法可以在不分配整数的情况下进行循环?

例如:

for i := 0; i < 500; i++ {
    PlayRandomGame()
}

我不需要也不想在这里分配i

英文:

In Go, if I want to do something 500 times, but I don't need to use the index, is there a way to loop without allocating an integer?

Like:

for i := 0; i &lt; 500; i++ {
    PlayRandomGame()
}

I don't need or want to allocate i there.

答案1

得分: 8

代码中没有要求将i分配在堆上。它很可能在栈上,当超出作用域时被释放,或者在寄存器中,无论哪种情况都不会创建垃圾。(如果你对这是如何可能的感到好奇,这种技术被称为逃逸分析。)
你可以在这个示例程序中看到TotalAlloc不增加

package main

import (
	"fmt"
	"runtime"
)

func loop() {
	for i := 0; i < 500; i++ {
	}
}

func main() {
	m1, m2 := new(runtime.MemStats), new(runtime.MemStats)
	runtime.ReadMemStats(m1)
	loop()
	runtime.ReadMemStats(m2)
	fmt.Println("TotalAlloc delta was", m2.TotalAlloc - m1.TotalAlloc)
}

为了确保循环执行500次,需要一个计数器,无论如何,即使你找到了一种隐含计数器的方法(比如r := make([]struct{}, 500); for range r {...}),在底层仍然会有一个计数器,只是没有变量名而已。

英文:

Nothing in that code requires i to be allocated on the heap. It's likely either on the stack, freed when it goes out of scope, or in a register, and in either case not creating garbage. (If you're curious about how this is possible, the technique is called escape analysis.)
You can see it in how TotalAlloc doesn't increase in this sample program:

package main

import (
	&quot;fmt&quot;
	&quot;runtime&quot;
)

func loop() {
	for i := 0; i &lt; 500; i++ {
	}
}

func main() {
	m1, m2 := new(runtime.MemStats), new(runtime.MemStats)
	runtime.ReadMemStats(m1)
	loop()
	runtime.ReadMemStats(m2)
	fmt.Println(&quot;TotalAlloc delta was&quot;, m2.TotalAlloc - m1.TotalAlloc)
}

A counter's necessary to make sure you do 500 iterations of a loop one way or the other, so even if you found some way to make the counter implied (r := make([]struct{}, 500); for range r {...}, say), there'd be no variable name but still be a counter under the covers.

答案2

得分: 2

如果你不喜欢计数器,可以使用以下代码:

for _ = range make([]struct{}, 500) {
    PlayRandomGame()
}

但是使用计数器的变体更符合惯用方式。

英文:

If you hate counters, you can use this:

for _ = range make([]struct{}, 500) {
    PlayRandomGame()
}

But the variant with a counter is more idiomatic.

huangapple
  • 本文由 发表于 2015年4月12日 10:47:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/29585423.html
匿名

发表评论

匿名网友

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

确定