在Go语言中使用循环和重复的函数调用可以使用for循环来实现。

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

For loop with repeated function call in Go

问题

我正在循环遍历状态变化,其中变化和条件在一个函数中定义,并希望编写一个for循环语句,其中只声明一次函数调用。

这段代码可以工作,但是重复使用message, flag = a.foo()感觉有点凌乱。在初始语句与后置语句相同时,是否有更有效的编写for循环的方法?

func (a *Example) foo() (string, bool) {
    // 函数影响a的状态
    // 在每一步返回message和是否达到条件的flag
}

func main() {
    // 逐个状态变化,直到触发flag
    for message, flag := a.foo(); flag; message, flag = a.foo() {
        fmt.Printf("%s\n", message)
    }
}

我希望能有一种类似于if语句的等效方式,像这样:

if message, flag := a.foo(); !flag {
    fmt.Printf("%s\n", message)
}

实际上,我希望只需将if改为for,但是遗憾的是,出现了expected ';'. found '{'的错误。

也许我要求太多了,但如果有答案,我很愿意听到。谢谢!

英文:

I'm looping over state changes where the change & condition are defined in a function and was hoping to write a for statement where I only declare the function call once.

This code works, but repeating message, flag = a.foo() feels messy. Is there a more effective way to write a for loop when the initial statement is the same as the post statement?

func (a *Example) foo() (string, bool) {
	// Function affects state of a
	// returns message on each step and flag if condition reached
}

func main() {
	// Step through each state change until flag is triggered
	for message, flag := a.foo(); flag; message, flag = a.foo() {
		fmt.Printf("%s\n", message)
	}
}

I was hoping that there would be some kind of equivalent to how nicely it fits in to an if statement like this:

if message, flag := a.foo(); !flag {
	fmt.Printf("%s\n", message)
}

In fact, I was rather hoping I could just change that if to a for but, alas, expected ';'. found '{'

I may well be asking too much, but if there is an answer I'd love to hear it. Thanks

答案1

得分: 3

据我所知,目前没有办法完全实现你想要的功能(虽然我也希望能够实现)。你可以使用一个“无限”循环,并手动编写中断条件,尽管这也不是一个很好的方法,类似于:

func main() {
    for {
        msg, flag := a.foo()
        if flag {
            break
        }
        fmt.Printf(...)
    }
}
英文:

As far as I know there is no way to do exactly what you want (though I'd love if it was possible too). You could use an "infinite" loop and write the break condition manually, although that also isn't too great, something like:

func main() {
    for {
        msg, flag := a.foo()
        if flag {
            break
        }
        fmt.Printf(...)
    }
}

答案2

得分: 1

如果你不打算提前跳出循环,一种选择是将代码结构化为使用通道和goroutine。所以,不要让Example.foo返回(string, bool),而是像这样做:

func (a *Example) foo() <-chan string {
    ch := make(chan string)
    go func() {
        // 将字符串发送到通道
        ch <- "first"
        ch <- "second"
        ...
        close(ch)
    }()
    return ch
}

然后可以使用以下代码循环遍历值:

for message := range a.foo() {
    fmt.Printf("%s\n", message)
}

如上所述,如果你计划提前退出循环,这种模式就不合适。如果这样做,那么供给通道的goroutine将保持阻塞状态,并且会一直存在于内存中,直到程序退出。

英文:

If you don't ever break out of the loop early, one option would be to structure your code to use a channel and goroutine. So rather than having Example.foo return (string, bool), do something like this:

func (a *Example) foo() &lt;-chan string {
    ch := make(chan string)
    go func() {
        // Send strings down the channel
        ch &lt;- &quot;first&quot;
        ch &lt;- &quot;second&quot;
        ...
        close(ch)
    }()
    return ch
}

You can then loop over the values with the following:

for message := range a.foo() {
    fmt.Printf(&quot;%s\n&quot;, message)
}

As mentioned above, this pattern is not appropriate if you plan to exit the loop early. If you do, then the goroutine feeding the channel will remain blocked, and stick around in memory until the program exits.

答案3

得分: 0

如果你不关心flagmessage的作用域,你可以在for循环之前声明它们(即如果你不打算通过for循环的初始化部分将flag和message作为局部临时变量)。

例如:

    var message string
	var flag bool = true

    // 在flag被触发之前遍历每个状态变化
    for ; flag; message, flag = a.foo() {
        fmt.Printf("%s\n", message)
    }
英文:

If you don't care about the scope of flag and message you could declare them before the for loop (i.e. if you aren't trying to make flag and message local temporary variables via the initialization section of the for loop).

For example:

    var message string
	var flag bool = true

    // Step through each state change until flag is triggered
    for ; flag; message, flag = a.foo() {
        fmt.Printf(&quot;%s\n&quot;, message)
    }

huangapple
  • 本文由 发表于 2014年4月26日 21:05:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/23311300.html
匿名

发表评论

匿名网友

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

确定