
go 语言中无法直接使用 try-catch,但可通过 defer + recover 在循环体内捕获 panic 并恢复执行,从而跳过异常项、继续后续迭代。关键在于将 defer-recover 正确置于每次迭代的作用域内(即循环体内),而非函数顶部。
go 语言中无法直接使用 try-catch,但可通过 defer + recover 在循环体内捕获 panic 并恢复执行,从而跳过异常项、继续后续迭代。关键在于将 defer-recover 正确置于每次迭代的作用域内(即循环体内),而非函数顶部。
在 Go 中,panic 会立即终止当前 goroutine 的正常执行流,除非被 recover() 显式捕获。与 Java 的 try-catch 不同,Go 的错误处理强调显式错误返回,但对不可控的运行时错误(如越界访问、nil 解引用),recover 是唯一可中断 panic 并恢复控制流的机制。
然而,你提供的代码存在两个关键问题:
-
defer位置错误:defer语句写在循环外部(实际在for循环块内,但未包裹在独立作用域中),导致所有defer被延迟到main函数结束时才统一执行,无法为每次迭代单独捕获 panic; -
切片越界:
arr是长度为 5 的切片([]int{5,6,7,8,9}),而循环从i = 6开始访问arr[6],必然触发panic: runtime error: index out of range。
✅ 正确做法是:将 defer + recover 逻辑封装在每次迭代的独立匿名函数或代码块中,确保 panic 发生时能被当次迭代的 recover 捕获,且不影响后续循环。
以下是修复后的完整示例:
package main
import "fmt"
func main() {
arr := []int{5, 6, 7, 8, 9}
fmt.Println("初始切片:", arr)
// ✅ 正确:为每次迭代创建独立的 defer-recover 作用域
for i := 0; i = 5)
}
}()
}
fmt.Println("最终切片(未修改超出部分):", arr)
}
? 关键要点说明:
-
defer必须位于可能触发 panic 的语句之前,且需在每次迭代内声明(如通过立即执行函数 IIFE); - 直接在
for循环体中写defer是无效的——Go 规范要求defer语句在函数返回前执行,所有defer会堆积并在main结束时集中运行,无法实现“单次迭代级恢复”; - 若需动态扩容切片,应使用
append()而非越界索引赋值(如arr = append(arr, i)),这是 Go 的惯用且安全方式; -
recover()只能在defer函数中调用才有效,且仅能捕获同一 goroutine 中的 panic。
? 替代建议(推荐优先级更高):
对于可预知的边界问题(如本例中的索引访问),应优先通过条件检查规避 panic,而非依赖 recover:
recover










