在Golang程序开发中,错误捕获与记录是保障程序稳定运行、快速排查问题的重要环节。合理的错误处理能让程序在出现异常时既不崩溃,又能留下足够的排查线索。

Golang基础错误捕获:error接口
Golang中大部分可预期的错误都通过error接口返回,这是最基础的错误捕获方式。函数执行后返回error类型结果,调用方判断error是否为nil即可知道是否出现错误。
下面是一个文件读取的错误捕获示例:
package main
import (
"fmt"
"os"
)
func readFile(path string) ([]byte, error) {
// 尝试打开文件,返回文件句柄和可能的错误
file, err := os.Open(path)
if err != nil {
// 返回错误,上层调用方处理
return nil, err
}
defer file.Close()
// 读取文件内容
content, err := os.ReadFile(path)
if err != nil {
return nil, err
}
return content, nil
}
func main() {
data, err := readFile("./test.txt")
if err != nil {
// 捕获到错误,进行记录或处理
fmt.Printf("读取文件失败:%v\n", err)
return
}
fmt.Printf("文件内容:%s\n", data)
}致命异常捕获:panic与recover配合
当程序出现不可恢复的严重错误时,会触发panic导致程序崩溃,此时可以通过recover在defer中捕获panic,避免程序直接退出,同时记录异常信息。
recover只能在defer函数中生效,用于捕获当前goroutine的panic。下面是使用示例:
package main
import (
"fmt"
"log"
"os"
)
func safeExecute() {
// defer函数中使用recover捕获panic
defer func() {
if err := recover(); err != nil {
// 记录捕获到的panic信息
log.Printf("捕获到致命异常:%v\n", err)
// 可以在这里做额外的清理工作
}
}()
// 模拟触发panic的场景
var arr []int
// 访问越界会触发panic
fmt.Println(arr[1])
}
func main() {
// 设置日志输出到文件
logFile, err := os.OpenFile("./error.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
fmt.Printf("打开日志文件失败:%v\n", err)
return
}
defer logFile.Close()
log.SetOutput(logFile)
safeExecute()
fmt.Println("程序继续执行,没有崩溃")
}goroutine中错误的捕获与记录
goroutine是Golang的并发单元,直接在goroutine中使用recover只能捕获当前goroutine的panic,无法传递到外层,因此需要通过通道或者错误收集机制把goroutine中的错误传递出来。
下面是使用通道传递goroutine错误的示例:
package main
import (
"fmt"
"log"
"time"
)
func task(id int, errChan chan<- error) {
defer func() {
if err := recover(); err != nil {
// 把goroutine中的panic转为error发送到通道
errChan <- fmt.Errorf("goroutine %d 发生异常:%v", id, err)
}
}()
// 模拟任务执行,id为2时触发panic
if id == 2 {
panic("模拟任务执行异常")
}
time.Sleep(time.Second)
fmt.Printf("goroutine %d 执行完成\n", id)
errChan <- nil
}
func main() {
taskNum := 3
errChan := make(chan error, taskNum)
// 启动多个goroutine执行任务
for i := 1; i <= taskNum; i++ {
go task(i, errChan)
}
// 收集所有goroutine的错误
for i := 0; i < taskNum; i++ {
err := <-errChan
if err != nil {
log.Printf("捕获到错误:%v\n", err)
}
}
fmt.Println("所有任务处理完成")
}错误记录的优化建议
实际项目中记录错误时,可以添加更多上下文信息,方便后续排查:
- 记录错误发生的时间、触发错误的函数名、相关参数
- 区分错误等级,比如普通错误、警告、致命异常,方便日志筛选
- 对于高频错误可以做限流记录,避免日志文件过大
- 敏感信息不要记录到错误日志中,防止信息泄露
如果需要更强大的日志功能,也可以使用第三方日志库,但核心的错误捕获逻辑和上述示例一致,只需要替换日志输出的部分即可。
Golangerror_handlingpanicrecoverlog修改时间:2026-06-02 15:59:16