M
Mr Sugiarto
Developer
24 Aug 2026 3 min read

Endpoint CRUD kita di Part 5 masih menerima input apapun tanpa validasi — title kosong atau slug kosong tetap akan tersimpan ke database. Di part ini kita tambahkan validasi request memakai go-playground/validator, library validasi paling umum dipakai di ekosistem Go.

Install Dependency

go get github.com/go-playground/validator/v10

Membuat Validator Reusable

Buat file validation/validation.go. Kita bungkus instance validator dan formatter pesan error di sini supaya bisa dipakai ulang di seluruh handler:

package validation

import (
	"fmt"

	"github.com/go-playground/validator/v10"
)

var Validate = validator.New()

func FormatErrors(err error) map[string]string {
	errors := make(map[string]string)

	validationErrors, ok := err.(validator.ValidationErrors)
	if !ok {
		return errors
	}

	for _, e := range validationErrors {
		errors[e.Field()] = message(e)
	}

	return errors
}

func message(e validator.FieldError) string {
	switch e.Tag() {
	case "required":
		return fmt.Sprintf("%s wajib diisi", e.Field())
	case "min":
		return fmt.Sprintf("%s minimal %s karakter", e.Field(), e.Param())
	case "max":
		return fmt.Sprintf("%s maksimal %s karakter", e.Field(), e.Param())
	case "email":
		return fmt.Sprintf("%s harus berupa email yang valid", e.Field())
	default:
		return fmt.Sprintf("%s tidak valid", e.Field())
	}
}

validator.New() cukup dibuat sekali sebagai package-level variable — instance ini aman dipakai bersamaan (concurrent-safe) dan menyimpan cache reflection struct supaya validasi berikutnya lebih cepat.

Menambahkan Tag Validasi ke Request Struct

Tambahkan tag validate pada postRequest di handlers/post_handler.go:

type postRequest struct {
	Title string `json:"title" validate:"required,min=3,max=255"`
	Slug  string `json:"slug" validate:"required,min=3,max=255"`
	Body  string `json:"body" validate:"required"`
}

Beberapa tag validasi yang dipakai:

  • required — field wajib diisi (tidak boleh nilai kosong/default)
  • min=3 / max=255 — panjang minimum/maksimum untuk string
  • Masih banyak tag lain (email, numeric, uuid, oneof, dst) yang bisa dicek di dokumentasi validator

Memanggil Validasi di Handler

Tambahkan pemanggilan validation.Validate.Struct(req) setelah BodyParser, baik di Create maupun Update:

if err := validation.Validate.Struct(req); err != nil {
	return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{
		"message": "validasi gagal",
		"errors":  validation.FormatErrors(err),
	})
}

Kalau ada field yang tidak lolos validasi, kita balas status 422 Unprocessable Entity beserta daftar error per field — format yang umum dipakai REST API modern supaya mudah ditangani di sisi frontend.

Testing Validasi

Jalankan server dan coba kirim request yang tidak lengkap:

curl -X POST http://127.0.0.1:3000/api/v1/posts \
  -H "Content-Type: application/json" \
  -d '{"title":"ab","slug":"","body":""}'

Responnya:

{
  "message": "validasi gagal",
  "errors": {
    "Body": "Body wajib diisi",
    "Slug": "Slug wajib diisi",
    "Title": "Title minimal 3 karakter"
  }
}

Kirim request yang valid, dan post akan tersimpan seperti biasa. Validasi ini akan kita pakai lagi nanti di Part 8 saat membuat endpoint Register dan Login.

M
Mr Sugiarto

Developer

Bagian dari Series: GoFiber Dasar - Belajar Fundamental Lewat REST API Blog

Belajar konsep-konsep dasar GoFiber (routing, handler, GORM, MySQL, JWT auth) dengan membangun REST API blog sederhana dari nol - lengkap dengan auten...

Lihat Series Lengkap