The error handling mechanism in the Gin framework is as follows:
1. Error handling overview
Gin provides a flexible error handling mechanism that can uniformly handle errors in middleware and handler functions, and return formatted responses.
2. Error handling in Context
Gin's Context object provides multiple error handling related methods:
go// Add error to Context c.Error(errors.New("something went wrong")) // Get all errors errors := c.Errors // Get last error lastError := c.Errors.Last()
3. Error recovery middleware
Gin provides a built-in recovery middleware to catch panics and recover the service.
go// Use built-in recovery middleware r.Use(gin.Recovery()) // Custom recovery middleware func CustomRecovery() gin.HandlerFunc { return func(c *gin.Context) { defer func() { if err := recover(); err != nil { c.JSON(500, gin.H{ "error": "Internal Server Error", "message": fmt.Sprintf("%v", err), }) c.Abort() } }() c.Next() } }
4. Unified error handling middleware
Create a middleware to uniformly handle all errors:
gofunc ErrorHandler() gin.HandlerFunc { return func(c *gin.Context) { c.Next() // Check if there are errors if len(c.Errors) > 0 { err := c.Errors.Last() switch err.Type { case gin.ErrorTypeBind: c.JSON(400, gin.H{ "error": "Validation Error", "details": err.Error(), }) case gin.ErrorTypePublic: c.JSON(400, gin.H{ "error": "Public Error", "details": err.Error(), }) default: c.JSON(500, gin.H{ "error": "Internal Server Error", }) } } } }
5. Custom error types
Define custom error types to distinguish different error situations:
gotype AppError struct { Code int Message string Err error } func (e *AppError) Error() string { return e.Message } func (e *AppError) Unwrap() error { return e.Err } // Use custom error func getUser(c *gin.Context) { user, err := userService.GetUser(1) if err != nil { c.Error(&AppError{ Code: 404, Message: "User not found", Err: err, }) return } c.JSON(200, user) }
6. Error response formatting
Unified error response format:
gotype ErrorResponse struct { Error string `json:"error"` Message string `json:"message,omitempty"` Code int `json:"code,omitempty"` Details string `json:"details,omitempty"` } func SendErrorResponse(c *gin.Context, statusCode int, err error) { response := ErrorResponse{ Error: http.StatusText(statusCode), } if appErr, ok := err.(*AppError); ok { response.Message = appErr.Message response.Code = appErr.Code response.Details = appErr.Err.Error() } else { response.Details = err.Error() } c.JSON(statusCode, response) }
7. Error logging
Log error information:
gofunc ErrorLogger() gin.HandlerFunc { return func(c *gin.Context) { c.Next() for _, err := range c.Errors { log.Printf("[%s] %s - Error: %v", c.Request.Method, c.Request.URL.Path, err.Error()) } } }
8. Best practices
- Use recovery middleware to prevent service crashes due to panics
- Create a unified error handling middleware
- Define clear error types and error codes
- Log detailed error information for debugging
- Return user-friendly error messages
- Distinguish between internal and external errors
- Use c.Error() instead of directly returning errors for unified handling
- Return detailed errors in development environment and generic errors in production environment
Gin's error handling mechanism can help us build robust applications, providing good user experience and error information for easy debugging.