如何在Go语言中复制do while循环?

48

我希望有一组代码能够在用户明确想要退出函数之前一直执行。例如:当用户运行程序时,他将看到2个选项:

  1. 再次运行
  2. 退出

这将使用switch case结构实现。如果用户按下1,则将执行与1相关联的一组函数,如果用户按下2,则程序将退出。我应该如何在Go中实现此场景?在Java中,我认为可以使用“do while”结构完成,但是Go不支持“do while”循环。以下是我尝试过的代码,但是这会进入无限循环:

func sample() {
    var i = 1
    for i > 0 {
        fmt.Println("Press 1 to run")
        fmt.Println("Press 2 to exit")
        var input string
        inpt, _ := fmt.Scanln(&input)
        switch inpt {
        case 1:
            fmt.Println("hi")
        case 2:
            os.Exit(2)
        default:
            fmt.Println("def")
        }
    }
}
无论输入什么,该程序都只打印“hi”。请问我在这里做错了什么? 谢谢。
8个回答

81

使用一个用 true 初始化的 bool 循环变量,在 Go 中可以用一个 for 循环来更直接地模拟一个 do..while

for ok := true; ok; ok = EXPR { }

更或多或少地等同于

do { } while(EXPR)

所以在您的情况下:

var input int
for ok := true; ok; ok = (input != 2) {
    n, err := fmt.Scanln(&input)
    if n < 1 || err != nil {
        fmt.Println("invalid input")
        break
    }

    switch input {
    case 1:
        fmt.Println("hi")
    case 2:
        // Do nothing (we want to exit the loop)
        // In a real program this could be cleanup
    default:
        fmt.Println("def")
    }
}

编辑:Playground(带有虚假的Stdin)

不过,诚然,在这种情况下,直接在循环中明确调用(标记的)breakreturnos.Exit可能会更清晰。


1
这应该被接受为答案,因为它是惯用语,并且完全复制了“do while”,而当前被接受的答案只复制了“while”语句。 - P.An
这是一个很好的简单答案,但它不允许您在条件中访问for范围内的变量。这个答案解决了这个问题。 - David Callanan
@David Callanan 我的意思是,修复起来并不难。只需对表达式执行 ok = ok 操作,并在循环结束时手动设置 ok 即可。 - Linear
@LinearZoetrope 很好,那也可以工作!条件完全是满足的 :) for ok := true; ok; ok = ok { ... } - David Callanan

15
当被问及这个问题时,以下答案是更好的选择针对特定的情况(我并不知道这会成为在谷歌搜索“golang do while循环”时的#1结果)。如果要通用地回答这个问题,请参见@LinearZoetrope's answer below
将您的函数放在一个for循环中:
package main

import (
    "fmt"
    "os"
)

func main() {
    fmt.Println("Press 1 to run")
    fmt.Println("Press 2 to exit")
    for {
        sample()
    }
}

func sample() {
    var input int
    n, err := fmt.Scanln(&input)
    if n < 1 || err != nil {
         fmt.Println("invalid input")
         return
    }
    switch input {
    case 1:
        fmt.Println("hi")
    case 2:
        os.Exit(2)
    default:
        fmt.Println("def")
    }
}

一个没有任何声明的 for 循环等同于其他类 C 语言中的 while 循环。请查看 Effective Go documentation,其中涵盖了 for 循环。

这段程序只会不停地打印“hi”。即使我们在命令行输入2,它也会打印“hi”,而不是退出程序。 - Vrushank Doshi
我的错误。需要修改switch case。 - Lander
1
所以原始输入的错误在于使用了Scanln的返回值。文档指出,返回值是一个错误/解析的参数数量,这不是你想要使用它的方式。这应该能让你开始工作了。 - Lander

15

Go 语言中的 do...while 可以是这样:

func main() {
    var value int
    for {
        value++
        fmt.Println(value)
        if value%6 != 0 {
            break
        }
    }
}

这个解决方案允许您在条件语句中访问for循环作用域内的变量,在某些情况下是必要的。 - David Callanan

13

在Go语言中,一个while循环可以像这样简单实现:

  package main

  import `fmt`

      func main() {
        for {
          var number float64
          fmt.Print(`insert an Integer eq or gr than 10!!!`)
          fmt.Scanf(`%f`, &number)
          if number >= 10 { break }
          fmt.Println(`sorry the number is lower than 10....type again!!!`)
        }

这是一个“无限”循环声明,而不是while循环。while循环会有一个条件。 - Victor Zamanian
2
@VictorZamanian,这里有一个条件:if number >= 10 { break }。从所有意图和目的来看,带有条件断开的无限循环与 do..while 循环是相同的,这正是 OP 所要求的。 - 3ocene
1
@VictorZamanian也许我误解了你的评论重点。听起来你是想说答案是不正确的或者他错了,认为这是在模拟while循环。 - 3ocene
3
@3ocene 不,不是的。你的推理是正确的。我可能只是在一段时间前对这个答案发表评论时错过了最后的条件。我的错误。 - Victor Zamanian

4

考虑使用“for-break”代替“do-while”。

foo.go

package main

import (
        "fmt"
)

func main() {
        i := 0
        for {
                i++
                if i > 10 {
                        break
                }
                fmt.Printf("%v ", i)
        }
        fmt.Println()
}

shell

$ go run foo.go
1 2 3 4 5 6 7 8 9 10

这与 for i := 0; i < 10; i++ { fmt.Printf("%v ", i) } 相同。也许你想把打印语句放在循环的顶部? - 3ocene

2
也许不是您想要的,但如果您想要做类似于这样的事情:
int i = 0;
while (i < 10) {
    cout << "incrementing i now" << endl;
    i++
}
cout << "done"

您需要在Go中执行以下操作:

    var i = 0 
    fmt.Println(i)
    for {
            if i < 10 {
                    fmt.Println("incrementing i now")
                    i++ 
            } else {
                    break
            }   
    }   
    fmt.Println("done")

2
Go语言确实有常规的“while循环”:for a > b { ... }。但是OP所要求的是一个do { ... } while (a > b);循环。 - Electric Coffee

1
sum := 1
    for sum < 1000 {
        sum += sum
    }

说明:

基本的for循环由三个由分号分隔的组件组成:

- 初始化语句:在第一次迭代之前执行。

- 条件表达式:在每次迭代之前计算。

- 后置语句:在每次迭代结束时执行。

初始化语句和后置语句是可选的。

因此,您可以只放入条件表达式。

// While (CONDITION = true){
//code to execute ....}

//In go : 
for CONDITION = true {
//code to execute}

0

这是最简洁的方法之一:

num := 10
for num > 0 {
    // do stuff here
    num--
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接