Дата: 2026-06-11 Статус: Accepted (требует реализации)
Валидация во всех handlers делается вручную через if req.Field == "" проверки. Нет единой схемы, неконсистентные ошибки, нет валидации форматов.
Использовать github.com/go-playground/validator/v10 — стандарт де-факто в Go.
| Библиотека | Причина отказа |
|---|---|
| go-ozzo/ozzo-validation | Функциональный стиль, менее популярный, меньше примеров |
| Ручная валидация | Неподдерживаемо, баги, дублирование |
| CUE / JsonSchema | Overengineering для REST API |
go get github.com/go-playground/validator/v10internal/validator/ с инициализацией и кастомными правилами// internal/validator/validator.go
func init() {
Validate.RegisterValidation("coordinate", validateCoordinate)
Validate.RegisterValidation("place_type", validatePlaceType)
Validate.RegisterValidation("user_role", validateUserRole)
Validate.RegisterValidation("currency", validateCurrency) // ISO 4217
}
func validateCoordinate(fl validator.FieldLevel) bool {
v := fl.Field().Float()
return v >= -90 && v <= 90 // для lat; для lng нужен отдельный или min/max
}
func validatePlaceType(fl validator.FieldLevel) bool {
v := fl.Field().String()
return v == "place" || v == "studio"
}
func validateUserRole(fl validator.FieldLevel) bool {
roles := map[string]bool{"customer": true, "landlord": true, "executor": true, "moderator": true, "superadmin": true}
return roles[fl.Field().String()]
}
type CreatePlaceRequest struct {
Title string `json:"title" validate:"required,min=1,max=255"`
Description *string `json:"description" validate:"omitempty,max=5000"`
Address *string `json:"address" validate:"omitempty,max=500"`
Lat float64 `json:"lat" validate:"required,coordinate,min=-90,max=90"`
Lng float64 `json:"lng" validate:"required,coordinate,min=-180,max=180"`
Type string `json:"type" validate:"required,place_type"`
Tags []string `json:"tags" validate:"dive,required,alphanum,max=50"`
Features []string `json:"features" validate:"dive,required,alphanum,max=50"`
HourlyRate *int `json:"hourly_rate" validate:"omitempty,min=0"`
Currency string `json:"currency" validate:"omitempty,len=3,uppercase,currency"`
MinHours int `json:"min_hours" validate:"min=0"`
}
{
"type": "https://api.photoplaces.ru/errors/validation-error",
"title": "Validation Failed",
"status": 422,
"detail": "One or more fields failed validation",
"instance": "/api/v1/places",
"errors": [
{ "field": "title", "message": "title is required" },
{ "field": "lat", "message": "lat must be between -90 and 90" }
]
}
Положительные:
Отрицательные:
#decision-record #validation #go #best-practice