> For the complete documentation index, see [llms.txt](https://sunwenfei.gitbook.io/sunwenfei/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sunwenfei.gitbook.io/sunwenfei/golang/golang-ji-chu-jiao-cheng/tiao-jian-xun-huan/xun-huan-yu-ju.md).

# 循环语句

循环语句用来重复执行一个代码块。

跟其他编程语言不同，Golang保持一种宁缺毋滥的态度，仅支持`for`语句循环，不支持`while`语句，后面我们会看到`for`语句完全能满足所有循环场景，因此也就不需要再多一种`while`循环语句了。

#### for循环语法

for循环语法如下：

```go
for initialization; condition; post {

}
```

其中初始化语句`initialization`仅执行一次。初始化语句执行完之后判断`condition`条件，如果条件成立，则执行大括号中的循环体代码块，仅接着执行`post`语句。`post`语句执行完之后会再次判断`condition`是否成立，如果仍然成立，那么继续再执行循环体代码块。该过程会循环不停的执行下去，直到`condition`条件不再成立为止。

`for`语句中的三个组成部分`initialization`、`condition`以及`post`都是非必须的。下面我们通过例子来更好的理解Golang中的`for`循环。

#### 例子

我们使用`for`循环来打印数字1到10。

```go
package main

import "fmt"

func main() {
    for i:= 1; i <= 10; i++ {
        fmt.Printf("%d ", i)
    }
}
```

[Go Playground在线运行](https://play.golang.org/p/MDaUaon5zqS) 这段程序中，变量`i`初始化为1。`for`循环的条件是判断`i <= 10`是否成立，如果成立，会打印出变量`i`的值，否则停止循环的执行，每次循环体执行后都是执行`i++`语句，将变量`i`加1，最终变量`i`会大于10，退出循环。

这段程序执行结果为：`1 2 3 4 5 6 7 8 9 10`。 `for`循环声明的变量`i`仅在`for`循环内部可见，无法在`for`循环外访问。

#### break

`break`语句用来强制退出`for`循环，然后接着执行`for`循环后面的代码。

现在我们通过使用`break`语句来打印数字1到5。

```go
package main

import "fmt"

func main() {  
    for i := 1; i <= 10; i++ {
        if i > 5 {
            break //loop is terminated if i > 5
        }
        fmt.Printf("%d ", i)
    }
    fmt.Printf("\nline after for loop")
}
```

[Go Playground在线运行](https://play.golang.org/p/3tbD60Xix95)

这段代码中的循环体每次执行时都会检查变量`i`的值，如果该值大于5，就会通过`break`语句强制终止循环的执行。然后执行仅接着`for`循环的代码。这段代码输出如下：

```
1 2 3 4 5 
line after for loop
```

#### continue

`continue`语句用来跳过当前循环体的执行，循环体内`continue`后面的语句都会被跳过，然后进入下一个迭代的执行。

下面我们利用`continue`语句来实现一个程序来打印1到10之间的偶数。

```go
package main

import "fmt"

func main() {  
    for i := 1; i <= 10; i++ {
        if i % 2 == 0 {
            continue
        }
        fmt.Printf("%d ", i)
    }
}
```

[Go Playground在线运行](https://play.golang.org/p/mn2WndDxtSj) 这段程序中通过`i % 2 == 0`来判断`i`是否是偶数，如果条件成立，那么执行`continue`语句，因此会跳过后面的打印语句，进入下一次迭代。该程序输出如下：`1 3 5 7 9`。

#### 嵌套for循环

一个`for`循环可以嵌套在另一个`for`循环执行。 我们实现一个程序打印下面所示的图案：

```
*
**
***
****
*****
```

下面的程序使用嵌套循环来打印上述图案。

```go
package main

import "fmt"

func main() {  
    n := 5
    for i := 0; i < n; i++ {
        for j := 0; j <= i; j++ {
            fmt.Print("*")
        }
        fmt.Println()
    }
}
```

[Go Playground在线运行](https://play.golang.org/p/fOl9h0UyQBW) 该程序中变量`n`表示行数。外层`for`循环中，变量`i`从0开始循环到4，共5次。内层`for`循环中，变量`j`从0开始循环到`i`。内层`for`循环每次执行打印符号`*`，外层`for`循环在每次内层`for`循环执行完之后打印一个换行，然后开始新的一行。

#### 标签

我们知道，可以通过`break`语句来退出当前`for`循环，注意这里退出的是当前循环。那么如果想在内层`for`循环退出外出`for`循环怎么做到呢？Golang中我们可以通过标签来实现。

我们先看一下下面这个例子：

```go
package main

import "fmt"

func main() {  
    for i := 0; i < 3; i++ {
        for j := 1; j < 4; j++ {
            fmt.Printf("i = %d , j = %d\n", i, j)
        }

    }
}
```

[Go Playground在线运行](https://play.golang.org/p/77fyT1MrU7I) 这个程序没什么特别的，就是个循环嵌套而已，输出如下：

```
i = 0 , j = 1
i = 0 , j = 2
i = 0 , j = 3
i = 1 , j = 1
i = 1 , j = 2
i = 1 , j = 3
i = 2 , j = 1
i = 2 , j = 2
i = 2 , j = 3
```

假如我们想在变量`i`和`j`的值相同时停止打印，即同时停止内、外层循环怎么实现呢？我们先尝试在内层循环增加`break`语句看下效果：

```go
package main

import "fmt"

func main() {  
    for i := 0; i < 3; i++ {
        for j := 1; j < 4; j++ {
            fmt.Printf("i = %d , j = %d\n", i, j)
            if i == j {
                break
            }
        }

    }
}
```

[Go Playground在线运行](https://play.golang.org/p/KNUFXaRoDgr) 跟我们想的一样，`break`仅能退出当前循环，无法退出双层循环，现在输出如下：

```
i = 0 , j = 1
i = 0 , j = 2
i = 0 , j = 3
i = 1 , j = 1
i = 2 , j = 1
i = 2 , j = 2
```

当然，如果可以在外层循环体也加个判断，然后使用`break`退出外层循环：

```go
package main

import "fmt"

func main() {  
    for i := 0; i < 3; i++ {
        j := 1
        for ; j < 4; j++ {
            fmt.Printf("i = %d , j = %d\n", i, j)
            if i == j {
                break
            }
        }
    if i == j {
            break
    }
    }
}
```

[Go Playground在线运行](https://play.golang.org/p/xhDOOBHvkbz) 现在可以输出我们想要的结果了：

```
i = 0 , j = 1
i = 0 , j = 2
i = 0 , j = 3
i = 1 , j = 1
```

这种方式固然能满足我们的要求，但是这里内外循环都做了判断，显得繁琐，借助**标签**我们可以更加优雅的实现这个功能：

```go
package main

import "fmt"

func main() {  
outer:  
    for i := 0; i < 3; i++ {
        for j := 1; j < 4; j++ {
            fmt.Printf("i = %d , j = %d\n", i, j)
            if i == j {
                break outer
            }
        }

    }
}
```

[Go Playground在线运行](https://play.golang.org/p/rW1fRZU_06f) 这里我们给外层循环加了个标签`outer`，在内层循环体内，我们通过`break outer`指定要退出的循环标签名称，来直接了当的退出外层循环，输出如下：

```
i = 0 , j = 1
i = 0 , j = 2
i = 0 , j = 3
i = 1 , j = 1
```

#### 更多例子

现在我们多实现几个例子来试用下`for`循环的各种其他用法。 下面的程序打印出0到10之间的偶数。

```go
package main

import "fmt"

func main() {  
    i := 0
    for ;i <= 10; { // initialisation and post are omitted
        fmt.Printf("%d ", i)
        i += 2
    }
}
```

[Go Playground在线运行](https://play.golang.org/p/CFlKZ8A_j3l) 前面我们已经提到过，`for`语句中的三个组成部分`initialization`(循环变量初始化)、`condition`(条件判断)以及`post`(循环收尾语句)都是非必须的。这个例子中的`for`语句就不包含`initialization`(循环变量初始化)和`post`(循环收尾语句)。这里循环变量`i`的初始化在`for`循环外就完成了，而且循环变量`i`的递增是在循环体内执行的。该程序输出：`0 2 4 6 8 10`。

上面程序中`for`语句中的分号`;`可以省略，写法如下：

```go
package main

import "fmt"

func main() {  
    i := 0
    for i <= 10 { // initialisation and post are omitted
        fmt.Printf("%d ", i)
        i += 2
    }
}
```

[Go Playground在线运行](https://play.golang.org/p/nBkzD_s4LF1) 细心就会发现，这不就是while循环的写法么？对！因此Golang中实现循环有`for`语句一种就够了。

我们可以在`for`语句中同时使用多个变量，比如下面的程序：

```go
package main

import "fmt"

func main() {  
    for no, i := 10, 1; i <= 10 && no <= 19; i, no = i + 1, no + 1 { //multiple initialisation and increment
        fmt.Printf("%d * %d = %d\n", no, i, no * i)
    }

}
```

[Go Playground在线运行](https://play.golang.org/p/llnYTxoDDTo) 这里在`for`语句中同时初始化了两个变量`no`和`i`，每次循环体执行结束后两个变量均加1。循环体执行的判断条件同时基于这两个变量来判断。该程序执行结果如下：

```go
10 * 1 = 10
11 * 2 = 22
12 * 3 = 36
13 * 4 = 52
14 * 5 = 70
15 * 6 = 90
16 * 7 = 112
17 * 8 = 136
18 * 9 = 162
19 * 10 = 190
```

#### 无限循环

创建无限循环的语句如下：

```go
for {

}
```

下面的程序会无限打印`Hello World`。

```go
package main

import "fmt"

func main() {  
    for {
        fmt.Println("Hello World")
    }
}
```

Golang中提供了一种非常方便的迭代数组的`for`循环方式，需要借助`range`，这个后面我们讲到数组时再详细讨论。
