Validation
package utils
import (
"github.com/go-playground/validator/v10"
)
func FormatValidationErrors(err error) map[string][]string {
errors := map[string][]string{}
if errs, ok := err.(validator.ValidationErrors); ok {
for _, e := range errs {
field := e.Field()
var message string
switch e.Tag() {
case "required":
message = "is required"
case "email":
message = "must be a valid email"
case "min":
message = "must be at least " + e.Param() + " characters"
case "max":
message = "must be at most " + e.Param() + " characters"
default:
message = "failed on " + e.Tag()
}
errors[field] = append(errors[field], message)
}
}
return errors
}
Response
package utils
type ApiResponse struct {
Data any `json:"data,omitempty"`
Message string `json:"message"`
Errors map[string][]string `json:"errors,omitempty"`
Pagination *PaginationMeta `json:"pagination,omitempty"`
}
type PaginationMeta struct {
Page int `json:"page"`
PerPage int `json:"per_page"`
TotalPages int `json:"total_pages"`
TotalItems int `json:"total_items"`
}
func BuildResponse(data any, message string, errors map[string][]string, pagination *PaginationMeta) ApiResponse {
return ApiResponse{
Data: data,
Message: message,
Errors: errors,
Pagination: pagination,
}
}
Response example (net/http)
package main
import (
"encoding/json"
"net/http"
"github.com/go-playground/validator/v10"
"yourmodule/utils"
)
type UserRequest struct {
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=8"`
}
var validate = validator.New()
func userHandler(w http.ResponseWriter, r *http.Request) {
var req UserRequest
_ = json.NewDecoder(r.Body).Decode(&req)
err := validate.Struct(req)
if err != nil {
errors := utils.FormatValidationErrors(err)
resp := utils.BuildResponse(nil, "Validation failed", errors, nil)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(resp)
return
}
resp := utils.BuildResponse(map[string]string{"status": "success"}, "User created", nil, nil)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(resp)
}
func main() {
http.HandleFunc("/user", userHandler)
http.ListenAndServe(":8080", nil)
}
Response (go fiber)
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/go-playground/validator/v10"
"yourmodule/utils"
)
type UserRequest struct {
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=8"`
}
var validate = validator.New()
func userHandler(c *fiber.Ctx) error {
req := new(UserRequest)
if err := c.BodyParser(req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(utils.BuildResponse(nil, "Invalid JSON", nil, nil))
}
if err := validate.Struct(req); err != nil {
errors := utils.FormatValidationErrors(err)
return c.Status(fiber.StatusBadRequest).JSON(utils.BuildResponse(nil, "Validation failed", errors, nil))
}
return c.JSON(utils.BuildResponse(map[string]string{"status": "success"}, "User created", nil, nil))
}
func main() {
app := fiber.New()
app.Post("/user", userHandler)
app.Listen(":8080")
}