feat(auth): 添加完整的用户认证API项目

- 实现用户注册、登录、JWT令牌认证功能
- 集成Gin、GORM、Viper、Zap等框架
- 添加密码加密、数据库操作、中间件等完整功能
- 配置多环境支持、日志轮转、CORS处理
- 创建完整的项目结构和配置文件体系
This commit is contained in:
liumangmang
2025-12-30 18:00:42 +08:00
parent 7f4527d501
commit b010f82221
139 changed files with 2772 additions and 103 deletions

View File

@@ -0,0 +1,31 @@
package main
import (
"go.uber.org/zap"
)
func main() {
// 1. 创建默认 Logger开发模式
logger, _ := zap.NewDevelopment()
defer logger.Sync() // 刷新缓冲区
// 2. 基础日志
logger.Info("Hello Zap!")
logger.Warn("This is a warning")
logger.Error("This is an error")
// 3. 结构化日志(带字段)
logger.Info("User logged in",
zap.String("username", "alice"),
zap.Int("user_id", 123),
zap.Bool("is_admin", true),
)
// 4. 不同日志级别
logger.Debug("Debug message")
logger.Info("Info message")
logger.Warn("Warn message")
logger.Error("Error message")
// logger.Fatal("Fatal message") // 会退出程序
// logger.Panic("Panic message") // 会触发 panic
}

View File

@@ -0,0 +1,22 @@
package main
import (
"go.uber.org/zap"
)
func main() {
// 创建生产模式 LoggerJSON 格式,性能更高)
logger, _ := zap.NewProduction()
defer logger.Sync()
logger.Info("Application started",
zap.String("version", "1.0.0"),
zap.Int("port", 8080),
)
logger.Error("Failed to process request",
zap.String("method", "GET"),
zap.String("path", "/api/users"),
zap.Int("status_code", 500),
)
}

View File

@@ -0,0 +1,51 @@
package main
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func main() {
// 1. 自定义配置
config := zap.Config{
Level: zap.NewAtomicLevelAt(zap.InfoLevel), // 日志级别
Development: false, // 生产模式
Encoding: "json", // 输出格式json/console
OutputPaths: []string{"stdout", "app.log"}, // 输出到控制台和文件
ErrorOutputPaths: []string{"stderr"},
EncoderConfig: zapcore.EncoderConfig{
TimeKey: "time",
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder, // 小写级别名
EncodeTime: zapcore.ISO8601TimeEncoder, // ISO8601 时间格式
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder, // 短路径
},
}
// 2. 创建 Logger
logger, _ := config.Build()
defer logger.Sync()
// 3. 使用 Logger
logger.Info("Custom logger initialized",
zap.String("env", "production"),
zap.Int("workers", 10),
)
logger.Warn("Low disk space",
zap.Int64("available_mb", 500),
zap.Int64("threshold_mb", 1000),
)
logger.Error("Database connection failed",
zap.String("host", "localhost"),
zap.Int("port", 3306),
zap.Error(nil),
)
}

View File

@@ -0,0 +1,48 @@
package main
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
)
func main() {
// 1. 配置日志轮转
logRotate := &lumberjack.Logger{
Filename: "./logs/app.log", // 日志文件路径
MaxSize: 10, // 每个日志文件最大 10MB
MaxBackups: 5, // 保留最近 5 个备份
MaxAge: 30, // 保留 30 天
Compress: true, // 压缩旧日志
}
// 2. 创建 WriteSyncer
writeSyncer := zapcore.AddSync(logRotate)
// 3. 配置 Encoder
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
// 4. 创建 Core
core := zapcore.NewCore(
zapcore.NewJSONEncoder(encoderConfig),
writeSyncer,
zap.InfoLevel,
)
// 5. 创建 Logger
logger := zap.New(core, zap.AddCaller())
defer logger.Sync()
// 6. 使用 Logger
for i := 0; i < 100; i++ {
logger.Info("Processing request",
zap.Int("request_id", i),
zap.String("method", "GET"),
zap.String("path", "/api/users"),
)
}
logger.Info("Log rotation configured successfully")
}

View File

@@ -0,0 +1,39 @@
package main
import (
"os"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func main() {
// 1. 配置 Encoder
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder // 带颜色的级别
// 2. 控制台输出console 格式)
consoleEncoder := zapcore.NewConsoleEncoder(encoderConfig)
consoleOutput := zapcore.AddSync(os.Stdout)
// 3. 文件输出json 格式)
fileEncoder := zapcore.NewJSONEncoder(encoderConfig)
file, _ := os.OpenFile("app.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
fileOutput := zapcore.AddSync(file)
// 4. 创建多输出 Core
core := zapcore.NewTee(
zapcore.NewCore(consoleEncoder, consoleOutput, zap.InfoLevel),
zapcore.NewCore(fileEncoder, fileOutput, zap.InfoLevel),
)
// 5. 创建 Logger
logger := zap.New(core, zap.AddCaller())
defer logger.Sync()
// 6. 使用 Logger
logger.Info("Application started")
logger.Warn("This is a warning")
logger.Error("This is an error")
}

View File

@@ -0,0 +1,29 @@
package main
import (
"go.uber.org/zap"
)
func main() {
logger, _ := zap.NewProduction()
defer logger.Sync()
// 1. 获取 Sugar Logger
sugar := logger.Sugar()
// 2. 使用格式化字符串(类似 fmt.Printf
sugar.Infof("User %s logged in with ID %d", "alice", 123)
sugar.Warnf("Low disk space: %d MB available", 500)
sugar.Errorf("Failed to connect to %s:%d", "localhost", 3306)
// 3. 使用键值对
sugar.Infow("User logged in",
"username", "alice",
"user_id", 123,
"is_admin", true,
)
// 4. 简洁日志
sugar.Info("Simple info message")
sugar.Warn("Simple warn message")
}

View File

@@ -0,0 +1,45 @@
package main
import (
"time"
"go.uber.org/zap"
)
func main() {
// 1. 创建可调整的日志级别
atom := zap.NewAtomicLevelAt(zap.InfoLevel)
// 2. 配置 Logger
config := zap.Config{
Level: atom,
Development: false,
Encoding: "json",
OutputPaths: []string{"stdout"},
ErrorOutputPaths: []string{"stderr"},
EncoderConfig: zap.NewProductionEncoderConfig(),
}
logger, _ := config.Build()
defer logger.Sync()
// 3. 初始日志级别为 Info
logger.Debug("Debug message - 1") // 不会输出
logger.Info("Info message - 1") // 会输出
// 4. 动态调整为 Debug 级别
time.Sleep(1 * time.Second)
atom.SetLevel(zap.DebugLevel)
logger.Info("Log level changed to Debug")
logger.Debug("Debug message - 2") // 现在会输出
logger.Info("Info message - 2") // 会输出
// 5. 动态调整为 Warn 级别
time.Sleep(1 * time.Second)
atom.SetLevel(zap.WarnLevel)
logger.Info("Log level changed to Warn")
logger.Info("Info message - 3") // 不会输出
logger.Warn("Warn message - 3") // 会输出
}

View File

@@ -0,0 +1,32 @@
package main
import (
"go.uber.org/zap"
)
func main() {
// 1. 创建 Logger
logger, _ := zap.NewProduction()
defer logger.Sync()
// 2. 设置为全局 Logger
zap.ReplaceGlobals(logger)
// 3. 在任何地方使用全局 Logger
doSomething()
doAnotherThing()
}
func doSomething() {
// 直接使用全局 Logger
zap.L().Info("Doing something",
zap.String("function", "doSomething"),
)
}
func doAnotherThing() {
// 使用全局 Sugar Logger
zap.S().Infow("Doing another thing",
"function", "doAnotherThing",
)
}

View File

@@ -0,0 +1,34 @@
package main
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func main() {
// 1. 使用 Sampling 采样(减少高频日志)
config := zap.NewProductionConfig()
config.Sampling = &zap.SamplingConfig{
Initial: 100, // 前 100 条日志全部记录
Thereafter: 100, // 之后每 100 条记录 1 条
}
logger, _ := config.Build()
defer logger.Sync()
// 2. 预分配字段(避免重复创建)
baseFields := []zapcore.Field{
zap.String("service", "user-service"),
zap.String("version", "1.0.0"),
}
// 3. 使用 With 创建子 Logger
userLogger := logger.With(baseFields...)
// 4. 高效记录日志
for i := 0; i < 1000; i++ {
userLogger.Info("Processing request",
zap.Int("request_id", i),
)
}
}

View File

@@ -0,0 +1,6 @@
{"level":"info","time":"2025-12-30T10:08:51.909+0800","caller":"05go-zap-demo/03zap_custom.go:36","msg":"Custom logger initialized","env":"production","workers":10}
{"level":"warn","time":"2025-12-30T10:08:51.909+0800","caller":"05go-zap-demo/03zap_custom.go:41","msg":"Low disk space","available_mb":500,"threshold_mb":1000}
{"level":"error","time":"2025-12-30T10:08:51.909+0800","caller":"05go-zap-demo/03zap_custom.go:46","msg":"Database connection failed","host":"localhost","port":3306,"stacktrace":"main.main\n\t/home/liumangmang/GolandProjects/learn-golang/Web开发/05go-zap-demo/03zap_custom.go:46\nruntime.main\n\t/usr/lib/go-1.22/src/runtime/proc.go:271"}
{"level":"\u001b[34mINFO\u001b[0m","ts":"2025-12-30T10:12:45.344+0800","caller":"05go-zap-demo/05zap_multi_output.go:35","msg":"Application started"}
{"level":"\u001b[33mWARN\u001b[0m","ts":"2025-12-30T10:12:45.344+0800","caller":"05go-zap-demo/05zap_multi_output.go:36","msg":"This is a warning"}
{"level":"\u001b[31mERROR\u001b[0m","ts":"2025-12-30T10:12:45.344+0800","caller":"05go-zap-demo/05zap_multi_output.go:37","msg":"This is an error"}

View File

@@ -0,0 +1,9 @@
module go-zap-demo
go 1.22.2
require (
go.uber.org/multierr v1.10.0 // indirect
go.uber.org/zap v1.26.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
)

View File

@@ -0,0 +1,6 @@
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=

View File

@@ -0,0 +1,101 @@
{"level":"INFO","ts":"2025-12-30T10:11:01.060+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":0,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":1,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":2,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":3,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":4,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":5,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":6,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":7,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":8,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":9,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":10,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":11,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":12,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":13,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":14,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":15,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":16,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":17,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":18,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":19,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":20,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":21,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":22,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":23,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":24,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":25,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":26,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":27,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":28,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":29,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":30,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":31,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":32,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":33,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":34,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":35,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":36,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":37,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":38,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":39,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":40,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":41,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":42,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":43,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":44,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":45,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":46,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":47,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":48,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":49,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":50,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":51,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":52,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":53,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":54,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":55,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":56,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":57,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":58,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":59,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":60,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":61,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":62,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":63,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":64,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":65,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":66,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":67,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":68,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":69,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":70,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":71,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":72,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":73,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":74,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":75,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":76,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":77,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":78,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":79,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":80,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":81,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":82,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":83,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":84,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":85,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":86,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":87,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":88,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":89,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":90,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":91,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":92,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":93,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":94,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":95,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":96,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":97,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":98,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:40","msg":"Processing request","request_id":99,"method":"GET","path":"/api/users"}
{"level":"INFO","ts":"2025-12-30T10:11:01.061+0800","caller":"05go-zap-demo/04zap_rotate.go:47","msg":"Log rotation configured successfully"}