在 Go 语言中,记录错误日志有多种方式,从标准库到第三方库都有成熟方案。下面按常见场景由浅入深介绍。
log(最简单)package main
import (
"log"
)
func main() {
log.Println("这是一条普通日志")
log.Printf("错误码: %d\n", 500)
log.Fatalln("发生致命错误,程序退出")
}
特点:
log + 文件输出package main
import (
"log"
"os"
)
func main() {
f, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
log.Fatal(err)
}
defer f.Close()
log.SetOutput(f)
log.Println("记录到文件的日志")
}
✅ 适合小型项目或工具程序
fmt.Errorf + log(推荐基础组合)func doSomething() error {
return fmt.Errorf("数据库连接失败: %w", err)
}
func main() {
if err := doSomething(); err != nil {
log.Println(err)
}
}
✅ 错误可包装
✅ 易读
✅ 适合大多数业务代码
errors + 错误上下文(Go 1.13+)import (
"errors"
"fmt"
"log"
)
func main() {
err := errors.New("原始错误")
wrapped := fmt.Errorf("上层错误: %w", err)
if err != nil {
log.Println(wrapped)
}
}
logrus(最流行)import (
"github.com/sirupsen/logrus"
)
func main() {
log := logrus.New()
log.SetLevel(logrus.InfoLevel)
log.Info("这是 info 日志")
log.Warn("这是 warn 日志")
log.Error("这是 error 日志")
}
特点:
zap(高性能,Uber 出品)import (
"go.uber.org/zap"
)
func main() {
logger, _ := zap.NewProduction()
defer logger.Sync()
logger.Info("服务启动",
zap.String("env", "prod"),
zap.Int("port", 8080),
)
logger.Error("数据库错误")
}
✅ 性能极高
✅ 适合高并发服务
❌ API 稍复杂
func handler(w http.ResponseWriter, r *http.Request) {
err := doSomething()
if err != nil {
log.Printf("请求失败: %v, path=%s", err, r.URL.Path)
http.Error(w, "server error", 500)
return
}
}
错误日志要包含上下文
log.Printf("用户登录失败: %v, userId=%d", err, userId)
不要吞掉错误
// ❌ 错误
_ = doSomething()
// ✅ 正确
if err != nil {
log.Println(err)
}
生产环境优先使用结构化日志
logruszap区分日志级别
| 方式 | 适合场景 |
|---|---|
| log | 小工具、脚本 |
| log + 文件 | 简单服务 |
| logrus | 通用 Web 服务 |
| zap | 高性能服务 |
如果你愿意,可以告诉我:
我可以给你一个完整可运行的日志模板。