1、使用标准库log包
使用Go的标准库log
包,可以快速打印日志到控制台或者文件。
package main
import (
"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 main
import (
"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 main
import (
"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 main
import (
"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 main
import (
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
var logger *zap.Logger
func 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 main
import (
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"os"
)
var log = logrus.New()
var logFile *os.File
func 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 = logFile
gin.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 main
import (
"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.Logger
log.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 main
import (
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.RFC3339TimeEncoder
encoderConfig.EncodeLevel = zapcore.LowercaseLevelEncoder
core := zapcore.NewCore(
zapcore.NewJSONEncoder(encoderConfig),
zapcore.AddSync(lumberJackLogger), // 使用 lumberjack 作为日志输出
zap.NewAtomicLevelAt(zapcore.InfoLevel), // 设置日志级别
)
// 创建zap logger
return zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)), nil
}
var logger *zap.Logger
func main() {
// 初始化zap logger
var err error
logger, 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()
}