循环控制 #
一、break语句 #
1.1 基本用法 #
break用于跳出当前循环:
go
for i := 0; i < 10; i++ {
if i == 5 {
break
}
fmt.Println(i)
}
// 输出: 0 1 2 3 4
1.2 在switch中使用 #
go
n := 2
switch n {
case 1:
fmt.Println("一")
case 2:
fmt.Println("二")
break // 可选,Go的switch默认break
case 3:
fmt.Println("三")
}
1.3 跳出嵌套循环 #
使用标签跳出外层循环:
go
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
break outer
}
fmt.Printf("(%d, %d) ", i, j)
}
}
// 输出: (0, 0) (0, 1) (0, 2) (1, 0)
1.4 实际应用 #
查找元素:
go
func find(matrix [][]int, target int) (int, int) {
for i, row := range matrix {
for j, val := range row {
if val == target {
return i, j
}
}
}
return -1, -1
}
提前退出:
go
func processUntilError(items []string) error {
for _, item := range items {
if err := process(item); err != nil {
return err
}
}
return nil
}
二、continue语句 #
2.1 基本用法 #
continue跳过本次迭代,继续下一次:
go
for i := 0; i < 5; i++ {
if i == 2 {
continue
}
fmt.Println(i)
}
// 输出: 0 1 3 4
2.2 在for-range中使用 #
go
numbers := []int{1, 2, 3, 4, 5}
for _, n := range numbers {
if n%2 == 0 {
continue
}
fmt.Println(n)
}
// 输出: 1 3 5
2.3 配合标签使用 #
跳到外层循环的下一次迭代:
go
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if j == 1 {
continue outer
}
fmt.Printf("(%d, %d) ", i, j)
}
}
// 输出: (0, 0) (1, 0) (2, 0)
2.4 实际应用 #
过滤处理:
go
func processValid(items []string) {
for _, item := range items {
if !isValid(item) {
continue
}
process(item)
}
}
跳过空值:
go
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
processLine(line)
}
三、goto语句 #
3.1 基本用法 #
goto无条件跳转到标签:
go
i := 0
start:
fmt.Println(i)
i++
if i < 5 {
goto start
}
// 输出: 0 1 2 3 4
3.2 标签定义 #
标签定义在语句前:
go
label:
// 语句
3.3 实际应用 #
错误处理:
go
func process() error {
var err error
if err = step1(); err != nil {
goto cleanup
}
if err = step2(); err != nil {
goto cleanup
}
if err = step3(); err != nil {
goto cleanup
}
return nil
cleanup:
doCleanup()
return err
}
资源释放:
go
func readFile(path string) ([]byte, error) {
f, err := os.Open(path)
if err != nil {
goto error
}
data, err := io.ReadAll(f)
if err != nil {
goto closeFile
}
f.Close()
return data, nil
closeFile:
f.Close()
error:
return nil, err
}
3.4 goto注意事项 #
- 不能跳过变量声明:
go
goto label
x := 10 // 错误:跳过变量声明
label:
fmt.Println(x)
- 不能跳入代码块:
go
goto label // 错误:不能跳入for块
for i := 0; i < 5; i++ {
label:
fmt.Println(i)
}
四、标签 #
4.1 定义规则 #
- 标签名在当前函数内唯一
- 标签后必须有语句
- 可以定义在for、switch、select之前
go
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == j {
continue outer
}
fmt.Printf("(%d, %d) ", i, j)
}
}
4.2 标签作用域 #
标签只在当前函数内有效:
go
func f1() {
label:
for i := 0; i < 3; i++ {
break label
}
}
func f2() {
// break label // 错误:label不在当前函数
}
五、实际应用示例 #
5.1 查找二维数组 #
go
func findInMatrix(matrix [][]int, target int) (int, int, bool) {
for i, row := range matrix {
for j, val := range row {
if val == target {
return i, j, true
}
}
}
return -1, -1, false
}
5.2 解析配置文件 #
go
func parseConfig(lines []string) (*Config, error) {
config := &Config{}
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
switch key {
case "host":
config.Host = value
case "port":
port, err := strconv.Atoi(value)
if err != nil {
return nil, err
}
config.Port = port
}
}
return config, nil
}
5.3 重试逻辑 #
go
func retryWithBackoff(fn func() error, maxAttempts int) error {
var lastErr error
backoff := time.Second
for attempt := 0; attempt < maxAttempts; attempt++ {
if err := fn(); err == nil {
return nil
} else {
lastErr = err
}
time.Sleep(backoff)
backoff *= 2
if backoff > 30*time.Second {
backoff = 30 * time.Second
}
}
return fmt.Errorf("after %d attempts: %v", maxAttempts, lastErr)
}
六、最佳实践 #
6.1 优先使用break/continue #
go
// 推荐
for {
if done {
break
}
}
// 不推荐
loop:
for {
if done {
goto end
}
}
end:
6.2 避免过度使用goto #
go
// 不推荐:使用goto模拟循环
i := 0
start:
fmt.Println(i)
i++
if i < 5 {
goto start
}
// 推荐:使用for
for i := 0; i < 5; i++ {
fmt.Println(i)
}
6.3 使用有意义的标签名 #
go
// 好
outerLoop:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
break outerLoop
}
}
// 不好
x:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
break x
}
}
七、总结 #
循环控制要点:
| 语句 | 说明 |
|---|---|
| break | 跳出当前循环 |
| continue | 跳过本次迭代 |
| goto | 无条件跳转 |
关键点:
- break:跳出循环或switch
- continue:跳过本次迭代
- goto:谨慎使用,避免造成混乱
- 标签:配合break/continue跳出嵌套循环
- 作用域:标签只在当前函数内有效
准备好学习函数了吗?让我们进入下一章!
最后更新:2026-03-26