package gin_release import ( "errors" "fmt" "github.com/gin-gonic/gin" "go.uber.org/zap" "goskeleton/app/global/consts" "goskeleton/app/global/variable" "goskeleton/app/utils/response" "io/ioutil" ) // ReleaseRouter 根据 gin 路由包官方的建议,gin 路由引擎如果在生产模式使用,官方建议设置为 release 模式 // 官方原版提示说明:[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. // 这里我们将按照官方指导进行生产模式精细化处理 func ReleaseRouter() *gin.Engine { // 切换到生产模式禁用 gin 输出接口访问日志,经过并发测试验证,可以提升5%的性能 gin.SetMode(gin.ReleaseMode) gin.DefaultWriter = ioutil.Discard engine := gin.New() // 载入gin的中间件,关键是第二个中间件,我们对它进行了自定义重写,将可能的 panic 异常等,统一使用 zaplog 接管,保证全局日志打印统一 engine.Use(gin.Logger(), CustomRecovery()) return engine } // CustomRecovery 自定义错误(panic等)拦截中间件、对可能发生的错误进行拦截、统一记录 func CustomRecovery() gin.HandlerFunc { DefaultErrorWriter := &PanicExceptionRecord{} return gin.RecoveryWithWriter(DefaultErrorWriter, func(c *gin.Context, err interface{}) { // 这里针对发生的panic等异常进行统一响应即可 // 这里的 err 数据类型为 :runtime.boundsError ,需要转为普通数据类型才可以输出 response.ErrorSystem(c, "", fmt.Sprintf("%s", err)) }) } // PanicExceptionRecord panic等异常记录 type PanicExceptionRecord struct{} func (p *PanicExceptionRecord) Write(b []byte) (n int, err error) { errStr := string(b) err = errors.New(errStr) variable.ZapLog.Error(consts.ServerOccurredErrorMsg, zap.String("errStrace", errStr)) return len(errStr), err }