第九篇 Loops 循环

欢迎来到Golang教程系列的第九篇

循环语句(loop)是用来重复执行一个代码块的。

for是Go中唯一的循环变量,Go没有那些在C语言中出现的whiledo while循环。

for循环语法

for initialosation; condition; post {
}

初始化语句只会执行一次,循环初始化之后,condition条件语句就会检查,如果condition条件判断为true,那就开始执行post语句,然后循环体{}里面的代码块接着执行。post语句会在每一次成功循环迭代后执行,post语句执行完成之后,condition语句会再次检查条件,如果为true,循环继续,不然的话,就终止循环。

所有三个部分就是初始化部分、条件判断部分,还有Post部分都是可选的。让我们看下面一个例子以便更好理解。

例子

我们写一个程序用来循环打印数字1到10.

package main

import (
	"fmt"
)

func main() {

	for i := 1; i <= 10; i++ {

		fmt.Printf(" %d",i)
	}
}

上面的程序中,i初始化为1,条件语句检查判断i <= 10,如果条件为true,就会打印i的值,否则就终止循环。在每次迭代之后,post语句会让i的值加1,一旦i的值大于10,那么就会终止循环。

上面的程序输出 1 2 3 4 5 6 7 8 9 10

在循环语句中声明的变量它的有效范围只在循环之内,因此,不可在循环体之外调用i

break

break语句是在for循环正常结束之前,用来突然终止程序的,它会把当前控制移动到for循环的结尾。

让我们用break写一个打印1到5的数字的程序。

package main

import (
	"fmt"
)

func main() {

	for i := 1; i <= 10; i++ {
		if i > 5 {
			break  // 终止循环
		}
		fmt.Printf(" %d",i)
	}

	fmt.Printf("\nline after for loop")
}

在上面的程序中,在每次迭代中,都会检查i的值,如果i的值大于5,那么就会执行break终止循环。在循环之后的打印语句就会执行。上面的程序将会输出

 1 2 3 4 5
line after for loo

continue

continue语句在for循环中是用来跳过当前迭代的,在当前迭代中,出现在continue语句后面的代码都不会被执行。循环将会跳进下一个迭代。

让我们用continue写一个打印1到10的所有奇数的程序。

package main

import (
	"fmt"
)

func main() {

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

}

在上面的程序中,if i%2 == 0,判断i除于2的余数是否为0,如果为0,那么i
为偶数,然后执行continue语句。当前控制跳到循环的下一个迭代。因此,continue后面的print语句不会执行,然后继续下一个迭代。上面的程序有输出: 1 3 5 7 9

嵌套循环

在一个for循环里面还有另外一个for循环,我们叫这为嵌套循环。

为更好地了解嵌套循环,让我们写一个顺序输出下面字符的程序。

*
**
***
****
*****

下面的程序用for循环打印序列,其中,n := 5中变量n保存了序列的行数。在我们的例子中是n为5,外层的循环迭代i是从04,内部循环j是从0到当前i的值。内循环每次迭代打印一个*,而外循环每次迭代打印新的一行。运行下面的程序,你就可看到序列输出。

package main

import (
	"fmt"
)

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

		fmt.Println()	
	}

}

labels 标记

labels 可以用来在内部for循环直接break跳出外部for循环。下面用一个简单的例子来说下这是什么意思。

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)
		}
	}

}

上面程序的输出

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

这没啥特别的。

但如果当ij相等时,我们想要停止打印。要实现这个,我们需要break外层的for循环。但是当i等于j时,在内层for循环新增一个break,只会跳出内层循环。

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
			}
		}
	}
	
}

在上面的程序中,当i等于j时,我在内层for循环新增了一个break,这个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

这并不是我们预期的输出,我们需要在ij都为1的时候停止打印。

labels能帮我们解决这个问题, labels可以用来break外层的for循环。下面让我们写一个关于怎么用labels的程序。

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
			}
		}
	}

}

在上面的程序中,我们在外层for循环新增了一个labelouter,并且通过指定break outerlabels跳出外层for循环。当ij相等时,程序就会停止打印。执行上面的程序将会输出。

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

更多的例子

让我们写更多的例子来覆盖所有不同的for循环。

下面的程序会打印出所有0到10的偶数

package main

import (
	"fmt"
)

func main() {
	i := 0
	for ; i <= 10; {  // 省略了初始化和post部分
		fmt.Printf("%d ", i)
		i += 2
	}
}

我们知道for循环有三个部分,初始化部分、条件部分,post部分都是可选的。在上面的程序中,初始化和post部分省略了,i在for循环之外初始化。循环只要执行i <= 10,i在循环体内每次都加2.上面的程序输出0 2 4 6 8 10

上面程序中的分号(semicolons)也是可以省略的。这个是可以考虑用来代替while循环。上面的程序可以重写成下面

package main

import (
	"fmt"
)

func main() {
	i := 0
	for i <= 10 {  // 分号都被省略了,只出现条件语句
		fmt.Printf("%d ", i)
		i += 2
	}
}

可以在for循环中声明和操作多个变量,我们用多个变量声明写一个程序打印出下面序列。

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  
package main

import (
	"fmt"
)

func main() {
	
	for no, i := 10, 1; i <= 10 && no <= 19; i, no = i+1, no+1 {

		fmt.Printf("%d * %d = %d\n", no, i, no*i)
	}
}

在上面的程序中,noi分别声明并初始化为10和1,在每次循环中都增加1.布尔操作符&&是用来条件判断i小于或等于10,且no是小于或等于19.

无限循环

下面是创建一个无限循环的语法。

for {
}

下面的程序将会连续不断的打印Hello World

package main

import "fmt"

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

如果你尝试执行上面的程序,你就会看到错误process took too long,你可以立即在你的机器上执行这个程序输出Hello World

还有一个构造范围可用于for循环中进行数组操作。我们将在学习数组的时候讨论这个问题

以上就是本篇的全部,感谢阅读,这是我第一次翻译,难免会有翻译不当的地方,如果有什么反馈和评论,欢迎提出来!

原文地址: https://golangbot.com/loops/