Collections of Go utility function

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")
}