package response import ( "net/http" "github.com/gin-gonic/gin" ) const ginAppErrorKey = "app_error" type AppError struct { HTTPStatus int `json:"-"` Code int `json:"code"` Message string `json:"message"` Detail string `json:"detail,omitempty"` Cause error `json:"-"` } func (e *AppError) Error() string { if e.Cause != nil { return e.Cause.Error() } return e.Message } func Success(c *gin.Context, data interface{}) { c.JSON(http.StatusOK, gin.H{ "code": 0, "message": "ok", "data": data, "request_id": getRequestID(c), }) } func SuccessWithStatus(c *gin.Context, status int, data interface{}) { c.JSON(status, gin.H{ "code": 0, "message": "ok", "data": data, "request_id": getRequestID(c), }) } func Error(c *gin.Context, err error) { appErr := Normalize(err) c.Set(ginAppErrorKey, appErr) _ = c.Error(appErr) c.JSON(appErr.HTTPStatus, gin.H{ "code": appErr.Code, "message": appErr.Message, "detail": appErr.Detail, "request_id": getRequestID(c), }) } func Normalize(err error) *AppError { if appErr, ok := err.(*AppError); ok { return appErr } return &AppError{ HTTPStatus: http.StatusInternalServerError, Code: 50000, Message: "internal_error", Detail: err.Error(), Cause: err, } } func AppErrorFromGin(c *gin.Context) (*AppError, bool) { if c == nil { return nil, false } value, ok := c.Get(ginAppErrorKey) if !ok || value == nil { return nil, false } appErr, ok := value.(*AppError) return appErr, ok && appErr != nil } func getRequestID(c *gin.Context) string { if rid, ok := c.Get("request_id"); ok { return rid.(string) } return "" }