1.for结构
如果想要重复执行某些语句,Go 语言中您只有 for 结构可以使用
1.1 基于计数器的迭代
基本格式为:
for 初始化语句; 条件语句; 修饰语句 {}
例子1:
package mainimport "fmt"func main() {for i := 0; i < 5; i++ {fmt.Printf("This is the %d iteration\n", i)}
}This is the 0 iteration
This is the 1 iteration
This is the 2 iteration
This is the 3 iteration
This is the 4 iteration
由花括号{}括起来的代码是重复执行的已知次数,该次数是由计数器i决定,循环开始前,i=0,紧接着是条件语句i < 5,在每次循环开始前都会进行判断,一旦判断结果为 false,则退出循环体。最后一部分为修饰语句i++,一般用于增加或减少计数器。
我们也可以在for循环中使用多个计数器,例如:
package mainimport "fmt"func main() {for i := 0; i < 5; i++ {for j := 0; j < 5; j++ {fmt.Println(i, j)}}
}
0 0
0 1
0 2
0 3
0 4
1 0
1 1
1 2
1 3
1 4
2 0
2 1
2 2
2 3
2 4
3 0
3 1
3 2
3 3
3 4
4 0
4 1
4 2
4 3
4 4
如果我们用for循环迭代一个Unicode编码的字符,会出现啥呢?请看下面的例子:
package mainimport "fmt"func main() {str := "Go is good!"fmt.Printf("The length of str is: %d\n", len(str))for ix := 0; ix < len(str); ix++ {fmt.Printf("Character on position %d is: %c \n", ix, str[ix])}
}The length of str is: 11
Character on position 0 is: G
Character on position 1 is: o
Character on position 2 is:
Character on position 3 is: i
Character on position 4 is: s
Character on position 5 is:
Character on position 6 is: g
Character on position 7 is: o
Character on position 8 is: o
Character on position 9 is: d
Character on position 10 is: !
课后习题:
1.使用 *
符号打印宽为 20,高为 10 的矩形。
package mainimport "fmt"func main() {width := 20height := 10// 使用 for 结构打印矩形for i := 0; i < height; i++ {for j := 0; j < width; j++ {// 如果是第一行或者最后一列,打印 *if i == 0 || i == height-1 || j == 0 || j == width-1 {fmt.Print("*")} else {// 其他位置打印空格fmt.Print(" ")}}// 换行fmt.Println()}
}
********************
* *
* *
* *
* *
* *
* *
* *
* *
********************
1.2 基于条件判断的迭代
for 结构的第二种形式是没有头部的条件判断迭代(类似其它语言中的 while 循环),基本形式为:
for 条件语句 {}
例子:
package mainimport "fmt"func main() {var i int = 5for i >= 0 {i = i - 1fmt.Printf("The variable i is now: %d\n", i)}
}
The variable i is now: 4
The variable i is now: 3
The variable i is now: 2
The variable i is now: 1
The variable i is now: 0
The variable i is now: -1
1.3 无限循环
如果 for 循环的头部没有条件语句,那么就会认为条件永远为 true,因此循环体内必须有相关的条件判断以确保会在某个时刻退出循环。
想要直接退出循环体,可以使用 break 语句(第 5.5 节)或 return 语句直接返回(第 6.1 节)。
但这两者之间有所区别,break 只是退出当前的循环体,而 return 语句提前对函数进行返回,不会执行后续的代码。
1.4 for-range结构
这是 Go 特有的一种的迭代结构,您会发现它在许多情况下都非常有用。它可以迭代任何一个集合,形式为:
for pos, char := range str {
...
}
例子:
package mainimport "fmt"func main() {str := "Go is good"fmt.Printf("The length of str is: %d\n", len(str))for pos, char := range str {fmt.Printf("Character on position %d is: %c \n", pos, char)}fmt.Println()
}The length of str is: 10
Character on position 0 is: G
Character on position 1 is: o
Character on position 2 is:
Character on position 3 is: i
Character on position 4 is: s
Character on position 5 is:
Character on position 6 is: g
Character on position 7 is: o
Character on position 8 is: o
Character on position 9 is: d
2.Break 与 continue
break:跳出循环
continue:忽略剩余的循环体而直接进入下一次循环的过程,但不是无条件执行下一次循环,执行之前依旧需要满足循环的判断条件
var i int = 5
for {i = i - 1fmt.Printf("The variable i is now: %d\n", i)if i < 0 {break}
}The variable i is now: 4
The variable i is now: 3
The variable i is now: 2
The variable i is now: 1
The variable i is now: 0
The variable i is now: -1package mainfunc main() {for i := 0; i < 5; i++ {if i == 2 {continue}print(i)print(" ")}}0 1 3 4
3.标签与 goto
for、switch 或 select 语句都可以配合标签(label)形式的标识符使用,即某一行第一个以冒号
package mainimport "fmt"func main() {LABEL1:for i := 0; i <= 5; i++ {for j := 0; j <= 5; j++ {if j == 4 {continue LABEL1}fmt.Printf("i is: %d, and j is: %d\n", i, j)}}}i is: 0, and j is: 0
i is: 0, and j is: 1
i is: 0, and j is: 2
i is: 0, and j is: 3
i is: 1, and j is: 0
i is: 1, and j is: 1
i is: 1, and j is: 2
i is: 1, and j is: 3
i is: 2, and j is: 0
i is: 2, and j is: 1
i is: 2, and j is: 2
i is: 2, and j is: 3
i is: 3, and j is: 0
i is: 3, and j is: 1
i is: 3, and j is: 2
i is: 3, and j is: 3
i is: 4, and j is: 0
i is: 4, and j is: 1
i is: 4, and j is: 2
i is: 4, and j is: 3
i is: 5, and j is: 0
i is: 5, and j is: 1
i is: 5, and j is: 2
i is: 5, and j is: 3
本例中,continue 语句指向 LABEL1,当执行到该语句的时候,就会跳转到 LABEL1 标签的位置。
您可以看到当 j==4 和 j==5 的时候,没有任何输出:标签的作用对象为外部循环,因此 i 会直接变成下一个循环的值,而此时 j 的值就被重设为 0,即它的初始值。如果将 continue 改为 break,则不会只退出内层循环,而是直接退出外层循环了。另外,还可以使用 goto 语句和标签配合使用来模拟循环。
package mainfunc main() {i:=0HERE:print(i)i++if i==5 {return}goto HERE
}01234
使用标签和 goto 语句是不被鼓励的,如果您必须使用 goto,应当只使用正序的标签(标签位于 goto 语句之后),但注意标签和 goto 语句之间不能出现定义新变量的语句,否则会导致编译失败