Gin 框架的日志默认是在控制台输出,本篇将使用 Gin 提供的 RecoveryWithWriter()
方法,封装一个中间件,使用 lumberjack
作为的写入器,将错误日志写入文件中;同时使用 github.com/gin-contrib/cors
,作下跨域处理。
go get -u gopkg.in/natefinch/lumberjack.v2
go get github.com/gin-contrib/cors
在 app/common/response/response.go
文件中,添加 ServerError()
方法,作为 RecoveryFunc
package response
import (
"github.com/gin-gonic/gin"
"jassue-gin/global"
"net/http"
"os"
)
// ...
func ServerError(c *gin.Context, err interface{}) {
msg := "Internal Server Error"
// 非生产环境显示具体错误信息
if global.App.Config.App.Env != "production" && os.Getenv(gin.EnvGinMode) != gin.ReleaseMode {
if _, ok := err.(error); ok {
msg = err.(error).Error()
}
}
c.JSON(http.StatusInternalServerError, Response{
http.StatusInternalServerError,
nil,
msg,
})
c.Abort()
}
// ...
新建 app/middleware/recovery.go
文件,编写:
package middleware
import (
"github.com/gin-gonic/gin"
"gopkg.in/natefinch/lumberjack.v2"
"jassue-gin/app/common/response"
"jassue-gin/global"
)
func CustomRecovery() gin.HandlerFunc {
return gin.RecoveryWithWriter(
&lumberjack.Logger{
Filename: global.App.Config.Log.RootDir + "/" + global.App.Config.Log.Filename,
MaxSize: global.App.Config.Log.MaxSize,
MaxBackups: global.App.Config.Log.MaxBackups,
MaxAge: global.App.Config.Log.MaxAge,
Compress: global.App.Config.Log.Compress,
},
response.ServerError)
}
新建 app/middleware/cors.go
文件,编写:
package middleware
import (
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
)
func Cors() gin.HandlerFunc {
config := cors.DefaultConfig()
config.AllowAllOrigins = true
config.AllowHeaders = []string{"Origin", "Content-Length", "Content-Type", "Authorization"}
config.AllowCredentials = true
config.ExposeHeaders = []string{"New-Token", "New-Expires-In", "Content-Disposition"}
return cors.New(config)
}
在 bootstrap/router.go
文件,编写:
func setupRouter() *gin.Engine {
if global.App.Config.App.Env == "production" {
gin.SetMode(gin.ReleaseMode)
}
router := gin.New()
router.Use(gin.Logger(), middleware.CustomRecovery())
// 跨域处理
// router.Use(middleware.Cors())
// ...
}
为了演示,这里我故意将数据库配置写错,请求登录接口,中间件成功生效
image-20231005192124398
接着查看 storage/logs/app.log
文件,错误信息成功写入到文件,内容如下:
runtime error: invalid memory address or nil pointer dereference
C:/Program Files/Go/src/runtime/panic.go:260 (0xeeb846)
panicmem: panic(memoryError)
C:/Program Files/Go/src/runtime/signal_windows.go:257 (0xeeb816)
sigpanic: panicmem()
C:/Users/xj/go/pkg/mod/gorm.io/gorm@v1.25.4/gorm.go:399 (0x14a8398)
(*DB).getInstance: if db.clone > 0 {
C:/Users/xj/go/pkg/mod/gorm.io/gorm@v1.25.4/chainable_api.go:201 (0x149dfbb)
(*DB).Where: tx = db.getInstance()
C:/www/go-project-demo/app/services/user.go:31 (0x1652c1e)
(*userService).Login: err = global.App.DB.Where("mobile = ?", params.Mobile).First(&user).Error
C:/www/go-project-demo/app/controllers/app/auth.go:18 (0x1653d78)
Login: if err, user := services.UserService.Login(form); err != nil {
C:/Users/xj/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174 (0x163bfe1)
(*Context).Next: c.handlers[c.index](c)
C:/Users/xj/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/recovery.go:102 (0x163bfcc)
CustomRecoveryWithWriter.func1: c.Next()
C:/Users/xj/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174 (0x163b106)
(*Context).Next: c.handlers[c.index](c)
C:/Users/xj/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/logger.go:240 (0x163b0e9)
LoggerWithConfig.func1: c.Next()
C:/Users/xj/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174 (0x163a1aa)
(*Context).Next: c.handlers[c.index](c)