Go 语言循环语句

只有 for 一种循环,以及它的四种形态和 range。

Beginner
Key PointsGo 没有 while 和 do-while,全部用 `for` 的四种写法表达。

四种形态

Go
// 1. 标准三段式
for i := 0; i < 3; i++ {
	fmt.Print(i, " ")
}
fmt.Println()

// 2. 只有条件(相当于 while)
n := 3
for n > 0 {
	fmt.Print(n, " ")
	n--
}
fmt.Println()

// 3. 无条件(相当于 while(true))
count := 0
for {
	count++
	if count == 3 {
		break
	}
}
fmt.Println("count =", count)

// 4. range
for i, v := range []string{"a", "b"} {
	fmt.Print(i, v, " ")
}
fmt.Println()
Output
0 1 2 
3 2 1 
count = 3
0a 1b 

break 与 continue

Go
// continue:跳过本次
for i := 1; i <= 5; i++ {
	if i%2 == 0 {
		continue
	}
	fmt.Print(i, " ")
}
fmt.Println()

// 带标签的 break:跳出多层
outer:
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			if i*j == 2 {
				fmt.Println("找到", i, j)
				break outer
			}
		}
	}
Output
1 3 5 
找到 1 2

Labels are Go's proper way out of nested loops. Without one, break exits only the innermost loop — a common source of "I thought it broke out" bugs.

range 的细节

Go
// 数组 / 切片:索引 + 值
for i, v := range []int{10, 20} {
	fmt.Println(i, v)
}

// 只要值
for _, v := range []int{10, 20} {
	fmt.Println(v)
}

// 字符串:索引 + rune
for i, r := range "Go语" {
	fmt.Printf("%d:%c ", i, r)
}
fmt.Println()

// map:键值顺序随机
for k, v := range map[string]int{"a": 1} {
	fmt.Println(k, v)
}
Output
0 10
1 20
10
20
0:G 1:o 2:语 
a 1
range 字符串时索引是字节偏移,不是字符序号。所以「语」的索引是 2 而不是 2 之后的 3——因为 G、o 各占 1 字节。

1.22 的循环变量变化

Go
// Go 1.21 及之前:所有闭包共享同一个 i,输出 3 3 3
// Go 1.22 起:每轮独立变量,输出 0 1 2
for i := 0; i < 3; i++ {
	go func() { fmt.Print(i, " ") }()
}
time.Sleep(10 * time.Millisecond)
Output
0 1 2 

This is a significant Go 1.22 semantic change. The old i := i workaround can be deleted; on 1.21 and earlier the same code prints 3 3 3.

goto

Go
i := 0
loop:
	if i < 3 {
		fmt.Print(i, " ")
		i++
		goto loop
	}
fmt.Println()
Output
0 1 2 

goto exists but is rarely used — mainly to escape deep nesting or in generated code. One hard rule: it cannot jump over a variable declaration.

Friends & Partners