1、使用标准库log包
使用Go的标准库log
包,可以快速打印日志到控制台或者文件。
package mainimport ("github.com/gin-gonic/gin""log"
)func main() {r := gin.Default()r.GET("/ping", func(c *gin.Context) {log.Println("请求方式" + c.Request.Method)c.JSON(200, gin.H{"message": "pong",})})r.Run()
}
2、使用Gin的内置日志功能
Gin框架提供了内置的日志功能,可以通过设置Logger
来开启。
package mainimport ("github.com/gin-gonic/gin"
)func main() {r := gin.Default()// 开启日志r.Use(gin.Logger())r.GET("/ping", func(c *gin.Context) {c.JSON(200, gin.H{"message": "pong",})})r.Run()
}
3、自定义日志
如果你需要更复杂的日志处理,比如将日志输出到不同的目的地,或者添加自定义的日志格式,你可以使用中间件来实现。
package mainimport ("github.com/gin-gonic/gin""log""time"
)func Logger() gin.HandlerFunc {return func(c *gin.Context) {// 在调用后续的处理函数之前,打印请求信息t := time.Now()c.Next() // 调用后续的处理函数// 在调用后续的处理函数之后,打印响应信息latency := time.Since(t)log.Printf("%s %s %s %d %s\n", c.ClientIP(), c.Request.Method, c.Request.URL.Path, c.Writer.Status(), latency)}
}func main() {r := gin.Default()// 使用自定义的Logger中间件r.Use(Logger())r.GET("/ping", func(c *gin.Context) {c.JSON(200, gin.H{"message": "pong",})})r.Run()
}
4、日志打印输出
package mainimport ("github.com/gin-gonic/gin""log""net/http""os"
)func main() {// 创建 Gin 实例r := gin.Default()// 创建日志文件f, err := os.OpenFile("gin.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)if err != nil {log.Fatalf("无法设置日志文件: %v", err)}defer f.Close()// 设置日志输出到文件log.SetOutput(f)gin.DefaultWriter = f // 将Gin的默认输出改为这个文件// 配置 Gin 的日志r.Use(gin.LoggerWithWriter(f))// 设置路由r.GET("/ping", func(c *gin.Context) {log.Printf(c.Request.RemoteAddr)log.Printf(c.Request.Proto)log.Printf(c.Request.Host)log.Printf(c.Request.Method)log.Printf(c.Request.RequestURI)c.String(http.StatusOK, "Hello World!")})// 启动服务器r.Run()
}
5、使用第三方日志库
你还可以使用第三方的日志库,如zap
、logrus
等,来提供更强大的日志功能。
zap:
package mainimport ("github.com/gin-gonic/gin""go.uber.org/zap"
)var logger *zap.Loggerfunc init() {logger, _ = zap.NewProduction()defer logger.Sync() // flushes buffer, if any
}func main() {r := gin.Default()r.Use(func(c *gin.Context) {logger.Info("正在处理请求", zap.String("path", c.Request.URL.Path))c.Next()})r.GET("/ping", func(c *gin.Context) {c.JSON(200, gin.H{"message": "pong",})})r.Run()
}
logrus:
package mainimport ("github.com/gin-gonic/gin""github.com/sirupsen/logrus""os"
)var log = logrus.New()
var logFile *os.Filefunc init() {// 以JSON格式而不是默认的ASCII格式器进行日志记录。log.Formatter = &logrus.JSONFormatter{}//输出到stdout而不是默认的stderr//可以是任何io.Writer,请参阅下面的文件示例//logFile, _ := os.Create("./gin.log")//使用os.Create函数创建文件时,默认情况下新创建的文件是空的,任何写入都会追加到文件末尾// 使用os.OpenFile而不是os.Create// flag参数设置为os.O_CREATE和os.O_APPEND,这意味着文件将被创建(如果它不存在)并且写入将追加到文件末尾// perm参数设置文件的权限(例如0644),这是一个常用的选项,表示文件对所有用户可读写,但只对拥有者可执行logFile, err := os.OpenFile("./gin.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)if err != nil {log.Fatal(err)}//defer f.Close()log.Out = logFilegin.SetMode(gin.ReleaseMode)gin.DefaultWriter = log.Out// 仅记录警告严重性或更高级别输出log.Level = logrus.InfoLevel
}func main() {// 创建一个默认的路由引擎r := gin.Default()defer logFile.Close()// GET:请求方式;/hello:请求的路径// 当客户端以GET方法请求/hello路径时,会执行后面的匿名函数r.GET("/hello", func(c *gin.Context) {log.WithFields(logrus.Fields{"animal": "狼","size": 10,}).Warn("一群狼在丛林中出现")// c.JSON:返回JSON格式的数据c.JSON(200, gin.H{"message": "Hello 狼!",})})r.Run(":8080")
}
6、gin 日志高级配置
1)配置Gin的Logger中间件
Gin框架的Logger中间件允许你配置日志的输出格式和级别。
go get -u gopkg.in/natefinch/lumberjack.v2
package mainimport ("github.com/gin-gonic/gin""gopkg.in/natefinch/lumberjack.v2""log"
)func main() {// 创建 lumberjack.Logger 实例lumberjackLogger := &lumberjack.Logger{Filename: "gin.log", // 日志文件路径MaxSize: 100, // 日志文件最大大小(MB)MaxBackups: 5, // 日志文件最大备份数MaxAge: 30, // 日志文件最大保存时间(天)Compress: true, // 是否压缩/归档旧文件}// 将标准库的 log 输出重定向到 lumberjack.Loggerlog.SetOutput(lumberjackLogger)// 创建 Gin 路由器r := gin.New()// 使用 lumberjack.Logger 作为 Gin 的日志输出r.Use(gin.LoggerWithWriter(lumberjackLogger))// 你的路由和中间件配置r.GET("/ping", func(c *gin.Context) {log.Println("请求方式" + c.Request.Method) // 这将输出到 lumberjack 配置的文件中c.JSON(200, gin.H{"message": "pong",})})// 运行 Gin 服务器r.Run()
}
无论是你的自定义日志输出还是 Gin 框架的日志输出,都会被写入到 lumberjack
配置的 gin.log
文件中。如果你使用的是其他日志库(如 zap
或 logrus
),你需要根据该库的文档来配置输出到 lumberjack.Logger
。
2)Gin集成zap&lumberjack
package mainimport (ginzap "github.com/gin-contrib/zap""github.com/gin-gonic/gin""go.uber.org/zap""go.uber.org/zap/zapcore""gopkg.in/natefinch/lumberjack.v2""time"
)// 初始化zap logger
func initZapLogger() (*zap.Logger, error) {// lumberjack 日志切割lumberJackLogger := &lumberjack.Logger{Filename: "./gin.log", // 日志文件路径MaxSize: 100, // 日志文件最大大小(MB)MaxBackups: 5, // 日志文件最大备份数MaxAge: 30, // 日志文件最大保存时间(天)Compress: true, // 是否压缩/归档旧文件}// 配置zap核心encoderConfig := zap.NewProductionEncoderConfig()encoderConfig.EncodeTime = zapcore.RFC3339TimeEncoderencoderConfig.EncodeLevel = zapcore.LowercaseLevelEncodercore := zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig),zapcore.AddSync(lumberJackLogger), // 使用 lumberjack 作为日志输出zap.NewAtomicLevelAt(zapcore.InfoLevel), // 设置日志级别)// 创建zap loggerreturn zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)), nil
}var logger *zap.Loggerfunc main() {// 初始化zap loggervar err errorlogger, err = initZapLogger()if err != nil {panic("初始化zap logger失败: " + err.Error())}defer logger.Sync() // flushes buffer, if any// 创建Gin路由器r := gin.New()// 使用zap logger中间件r.Use(ginzap.Ginzap(logger, time.RFC3339, true))// 其他Gin配置...// 你的路由和中间件配置r.GET("/ping", func(c *gin.Context) {logger.Info("收到一个到/ping的GET请求")c.JSON(200, gin.H{"message": "pong",})})// 运行Gin服务器r.Run()
}