北屋教程网

专注编程知识分享,从入门到精通的编程学习平台

Gin 框架学习实录 · 第7篇:日志模块封装

前言

在完成了用户模块 CRUD、统一响应结构与错误码、分页封装之后,我们已经搭建出一个较为完整的 Gin 项目基础骨架。

但要想让项目 在生产环境中更加可观测、易排查、可追踪 ,日志模块就必不可少了。

日志模块封装(使用 zap 实现)

我们使用 Uber 出品的高性能日志库 zap 来封装日志模块。

步骤一:安装 zap 日志库

go get go.uber.org/zap

#技术分享 #掘金步骤二:创建日志模块

logger/logger.go 中初始化日志模块:

package logger

import ( "go.uber.org/zap" )

var Log *zap.SugaredLogger

func InitLogger() { zapLogger, err := zap.NewProduction() if err != nil { panic(" 初始化日志失败: " +

}

Log = zapLogger.Sugar() }

步骤三:在 main.go 中初始化日志

import (
    "gin-learn-notes/logger"
)

func main() { logger.InitLogger() defer logger.Log.Sync()

}

这里我要说一下 我们在上面的 main.go 里面加入了这行 defer logger.Log.Sync() 。这个我刚开始也不了解 后面才知道:

zap 的日志输出是异步 + 缓冲的

默认情况下,zap 会将日志内容写入内存缓冲区,然后异步地刷新到标准输出或文件中,这样做可以提升日志性能,但也带来一个问题

如果程序还没来得及把日志写入目标输出,主程序就退出了,那些缓冲中的日志就可能“丢失

所以我们要在程序退出前,主动调用 .Sync() 方法

这个方法的作用就是:

  • 刷新 zap 的缓冲区
  • 确保所有日志都已经被写入(终端 or 文件)

步骤四:项目中任意位置调用日志

import "gin-learn-notes/logger"

logger.Log.Info("用户列表:", users)

使用 zap.SugaredLogger,可以像 Printf 一样使用格式化日志,同时性能也非常优秀。后续也可以替换为自定义配置、输出到文件、JSON 格式等。

我们就可以在控制台看到日志输出:


配置化日志 + 写入文件 + 按天切割

一般我们日志都会存放到专门的日志目录里面 不会像这样直接输出到控制台中 所以我们可以把日志写入日志文件,并自动切割。

实现方案:zap + lumberjack 搭配使用

lumberjack 是一个非常轻量、稳定的日志切割工具,支持:

  • 最大文件大小
  • 最多保留几个日志文件
  • 是否压缩历史日志
  • 按天/按大小切割等

安装 lumberjack

go get github.com/natefinch/lumberjack

我们可以在 logger.go 里加如下功能:

import (
    "go.uber.org/zap/zapcore"
    "github.com/natefinch/lumberjack"
)

func getLogWriter() zapcore.WriteSyncer { lumberJackLogger := &lumberjack.Logger{ Filename: "logs/app.log", MaxSize: 10, MaxBackups: 5, MaxAge: 30, Compress: true, } return zapcore.AddSync(lumberJackLogger) }

然后我们修改下之前的 InitLogger 函数:

func InitLogger() {

    encoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())

writer := getLogWriter()

level := zapcore.InfoLevel

core := zapcore.NewCore(encoder, writer, level)

logger := zap.New(core, zap.AddCaller()) Log = logger.Sugar() }

完整文件示例(logger/logger.go):

package logger

import ( "github.com/natefinch/lumberjack" "go.uber.org/zap" "go.uber.org/zap/zapcore" )

var Log *zap.SugaredLogger

func InitLogger() { encoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())

writer := getLogWriter()

level := zapcore.InfoLevel

core := zapcore.NewCore(encoder, writer, level)

logger := zap.New(core, zap.AddCaller()) Log = logger.Sugar() }

func getLogWriter() zapcore.WriteSyncer { lumberJackLogger := &lumberjack.Logger{ Filename: "logs/app.log", MaxSize: 10, MaxBackups: 5, MaxAge: 30, Compress: true, } return zapcore.AddSync(lumberJackLogger) }

我们需要在项目根目录提前创建 logs/ 目录:

mkdir logs

否则第一次运行时 zap 会找不到路径报错。当然我们也可以创建日志目录判断(避免首次运行时报错):

func getLogWriter() zapcore.WriteSyncer {

    if _, err := os.Stat("logs"); os.IsNotExist(err) {
       _ = os.Mkdir("logs", 0755)
    }

lumberJackLogger := &lumberjack.Logger{ Filename: "logs/app.log", MaxSize: 10, MaxBackups: 5, MaxAge: 30, Compress: true, } return zapcore.AddSync(lumberJackLogger) }

我们在此运行一下之前写日志的地方接口后看看是否记录到 logs/app.log 里面:

项目结构继续演进(新增日志模块)

gin-learn-notes/
├── config/
│   └── database.go
│
├── controller/
│   ├── hello.go
│   ├── index.go
│   └── user.go
│
├── core/
│   └── response/
│       ├── code.go
│       ├── page.go
│       └── response.go
│
├── logger/
│   └── logger.go
│
├── logs/
│   └── app.log
│
├── model/
│   └── user.go
│
├── request/
│   ├── page_request.go
│   └── user_request.go
│
├── router/
│   └── router.go
│
├── service/
│   └── user_service.go
│
├── utils/
│   ├── paginate.go
│   ├── response.go
│   └── validator.go
│
├── main.go
├── go.mod
├── .gitignore
└── README.md

最后

本篇我们完成了日志模块的初步封装,包括:

  • 使用 zap 构建高性能日志组件
  • 搭配 lumberjack 实现日志自动切割
  • 日志输出到 logs/ 目录,便于运维分析
  • 可在项目中任意位置使用统一日志输出格式

到这为止,我们的 Gin 项目已经具备了清晰的日志体系,可以支撑后续开发与调试。

但是呢 我们注意到:目前数据库连接信息、端口号、日志路径等,还是直接写在代码里的

dsn := "root:123456@tcp(127.0.0.1:3306)/demo?..."

但在实际开发中,这些配置一般都会写在 .envconfig.yaml 等配置文件中, 而不是硬编码到逻辑里

所以 接下来我们将使用 config.yaml 实现全局配置管理:

  • 管理数据库连接信息
  • 设置服务端口
  • 配置日志路径、日志等级
  • 封装成统一的 config 模块,项目启动时自动加载

实现更灵活的配置方式,便于后续环境切换、配置热更新、部署管理等场景

本篇对应代码提交记录

commit: 3cafdb4018d626705c6673f3299a16a98db0f1e6

GitHub 源码地址:github.com/luokakale-k…

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言