1. for 循环格式
Go
语言仅支持一种循环语句即 for
循环,它有 3 种形式,只有其中的一种使用分号。
- 和 C 语言的 for 一样
for init; condition; post { }
init
: 一般为赋值表达式,给控制变量赋初值,初始语句是在第一次循环前执行的语句,一般使用初始语句执行变量初始化,如果变量在此处被声明,其作用域将被局限在这个 for
的范围内。
condition
: 关系表达式或逻辑表达式,循环控制条件,每次循环开始前都会计算条件表达式,如果表达式为 true
,则循环继续,否则结束循环,条件表达式可以被忽略,忽略条件表达式后默认形成无限循环。
post
: 一般为赋值表达式,给控制变量增量或减量;
可以看到比较大的一个不同在于 for
后面的条件表达式不需要用圆括号()
括起来。左花括号{
必须与 for
处于同一行。
Go
语言中的 for
循环与 C
语言一样,都允许在循环条件中定义和初始化变量,唯一的区别是, Go
语言不支持以逗号为间隔的多个赋值语句,必须使用平行赋值的方式来初始化多个变量。
示例-1:
var i int
for ; ; i++ {
if i > 10 {
break
}
}
- 和
C
的while
一样
for condition { }
示例-2
var i int
for i <= 10 {
i++
}
- 和
C
的for(;;)
一样,无限循环
for { }
示例-3
var i int
for {
if i > 10 {
break
}
i++
}
2. for 循环示例
package main
import "fmt"
func main() {
var b int = 15
var a int
numbers := [6]int{1, 2, 3, 5}
/* for 循环 */
for a := 0; a < 10; a++ { // 左花括号{必须与 for 处于同一行
fmt.Printf("a 的值为: %d\n", a)
}
for a < b {
a++
fmt.Printf("a 的值为: %d\n", a)
}
for i, x:= range numbers {
fmt.Printf("第 %d 位 x 的值 = %d\n", i,x)
}
}
3. 嵌套 for 循环
package main
import "fmt"
func main() {
/* 定义局部变量 */
var i, j int
for i=2; i < 100; i++ {
for j=2; j <= (i/j); j++ {
if(i%j==0) {
break; // 如果发现因子,则不是素数
}
}
if(j > (i/j)) {
fmt.Printf("%d 是素数\n", i);
}
}
}
4. for 循环应用
Go
语言中 range
关键字用于 for
循环中迭代数组 (array
)、切片(slice
)、通道(channel
)或集合 (map
) 的元素。通过 for range
遍历的返回值有一定的规律:
- 数组、切片、字符串返回索引和值。
map
返回键和值。- 通道(
channel
)只返回通道内的值。
4.1 访问数组
for index , value :=range arry{}
for index := range arry{}
for _, value :=range arry{}
在上面的例子中将 key 变成了下划线_
,这里的下划线就是匿名变量。
- 可以理解为一种占位符
- 匿名变量本身不会进行空间分配,也不会占用一个变量的名字
- 在
for range
可以对key
使用匿名变量,也可以对value
使用匿名变量
package main
import "fmt"
func main() {
array := [3]int{10, 20, 30}
for i, v := range array {
fmt.Printf("index is %v, value is %v\n", i, v)
}
for _, v := range array {
fmt.Printf("value is %v\n", v)
}
for i := range array {
fmt.Printf("index is %v\n", i)
}
}
输出:
index is 0, value is 10
index is 1, value is 20
index is 2, value is 30
value is 10
value is 20
value is 30
index is 0
index is 1
index is 2
4.2 访问切片
for index, value :=range slice{}
for index := range slice{}
for _, value :=range slice{}
代码演示和数组类似,只需要做如下改动:
array := [3]int{10, 20, 30} // 数组
array := []int{10, 20, 30} // 切片
4.3 访问字典
对于 map
类型来说,for range 遍历时, key
和 value
分别代表 map
的索引键 key
和索引对应的值,一般被称为 map
的键值对,因为它们是一对一对出现的。
for key , value := range map{}
for key := range map {}
4.4 访问字符串
range
也可以用来枚举 Unicode
字符串。第一个参数是字符的索引,第二个是字符(Unicode的值)本身。
for index, value := range string
for index := range string
示例:
package main
import "fmt"
func main() {
s := "hello"
for i := range s {
fmt.Printf("value is %v\n", s[i])
}
}
4.5 访问通道
for range
可以遍历通道( channel
),但是通道在遍历时,只输出一个值,即管道内的类型对应的数据。
for value :=range channel{}
代码示例:
c := make(chan int)
go func() {
c <- 1
c <- 2
c <- 3
close(c)
}()
for v := range c {
fmt.Println(v)
}
4. 循环控制语句
4.1 goto
goto
语句用于函数的内部的跳转,需要配合标签一起使用, 具体的格式如下:
goto Lable
goto Lable
的语义是跳转到标签名后的语句处执行, goto
语句有以下几个特点:
goto
语句只能在函数内跳转;goto
语句不能跳过内部变量声明语句,这些变量在goto
语句的标签语句处又是可见的;
goto L // BAD ,跳过v := 3 这条语句是不允许的
v := 3
L :
goto
语句只能跳到同级作用域或者上层作用域内,不能跳到内部作用域内;
if n%2 == 1 {
goto LL
}
for n > 0 {
f()
n--
LL:
f()
n--
}
代码示例:
package main
import "fmt"
func main() {
for x := 0; x < 10; x++ {
for y := 0; y < 10; y++ {
if y == 2 {
// 跳转到标签
goto breakHere
}
}
}
// 手动返回, 避免执行进入标签
return
// 标签
breakHere:
fmt.Println("done")
}
4.2 continue
跳过当前循环的剩余语句,仅能用于 continue
语句,然后继续进行下一轮循环,有两种格式:
-
单独使用,用于跳出
continue
当前所在的for
循环的本次迭代; -
和标签一起使用,用于跳出标签所标识的
for
语句的本次选代,但标签和continue
必须在同一个函数内。
例如:
package main
import "fmt"
func main() {
OuterLoop:
for i := 0; i < 2; i++ {
for j := 0; j < 5; j++ {
switch j {
case 2:
fmt.Println(i, j)
continue OuterLoop
}
}
}
}
4.3 break
break
用于函数内跳出 for
、 switch
、 select
语句的执行,有两种使用格式:
-
单独使用,用于跳出
break
当前所在的for
、switch
、select
语句的执行; -
和标签一起使用,用于跳出标签所标识的
for
、switch
、select
语句的执行,可用于跳出多重循环,但标签和break
必须在同一个函数内。
例如:
package main
import "fmt"
func main() {
Ll:
for i := 0; ; i++ {
for j := 0; ; j++ {
if i >= 5 {
// 跳到 Ll 标签所在的 for 循环 i++ 处执行
fmt.Println(i)
break Ll
//the following is not executed
}
if j > 10 {
fmt.Println(j)
// 默认仅跳到离 break 最近的内层循环 j++ 处执行
break
}
}
}
}
不带 label
的 break
语句中断执行并跳出的,是同一函数内 break
语句所在的最内层的 for
、switch
或 select
。
func main() {
var sl = []int{5, 19, 6, 3, 8, 12}
var firstEven int = -1
// find first even number of the interger slice
loop:
for i := 0; i < len(sl); i++ {
switch sl[i] % 2 {
case 0:
firstEven = sl[i]
break loop
case 1:
// do nothing
}
}
println(firstEven) // 6
}
我们定义了一个 label:loop
,这个 label
附在 for
循环的外面,指代 for
循环的执行。当代码执行到break loop
时,程序将停止 label loop
所指代的 for
循环的执行。