Data Validation in Go: Libraries, Examples, and Best Practices

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Data Validation in Go (Golang): Tools, Examples, and Best Practices



Data validation is one of the key stages in developing any web application or API. In Go (Golang), this task is solved particularly elegantly thanks to strong typing, powerful libraries, and built-in capabilities. In this article, we will break down the main approaches to data validation, popular libraries, and provide practical code examples.



Why is validation needed in Go?

Go compiles to native code and does not have a built-in reflection system like Python or JavaScript. However, developers have created several excellent libraries that allow you to:

  • Validate struct fields against formats (email, URL, phone);
  • Set constraints (min, max, required);
  • Create custom validators for business logic;
  • Integrate with web frameworks (Gin, Echo, Fiber).


1. The go-playground/validator library (most popular)

go-playground/validator is the de facto standard for validating structs in Go. It uses tags in struct fields and supports over 100 built-in rules.



package main

import ( "fmt" "github.com/go-playground/validator/v10")

type User struct { Name string `validate:"required,min=2,max=50"` Email string `validate:"required,email"` Age int `validate:"gte=18,lte=120"`}

func main() { validate := validator.New() user := User{ Name: "A", Email: "invalid-email", Age: 15, } err := validate.Struct(user) if err != nil { for _, e := range err.(validator.ValidationErrors) { fmt.Printf("Field: %s, Error: %s, Value: %v", e.Field(), e.Tag(), e.Value()) } }}


Output:

Field: Name, Error: min, Value: AField: Email, Error: email, Value: invalid-emailField: Age, Error: gte, Value: 15


2. The ozzo-validation library (an alternative with method chaining)

ozzo-validation offers a more declarative style without tags. It is suitable for cases where the struct cannot be modified or dynamic validation is needed.



package main

import ( "fmt" "github.com/go-ozzo/ozzo-validation/v4" "github.com/go-ozzo/ozzo-validation/v4/is")

type Product struct { Name string Price float64}

func main() { p := Product{Name: "", Price: -10} err := validation.ValidateStruct(&p, validation.Field(&p.Name, validation.Required, validation.Length(1, 100)), validation.Field(&p.Price, validation.Required, validation.Min(0.01)), ) if err != nil { fmt.Println(err) }}


3. Custom validators

Often, validation not covered by built-in rules is required. For example, password validation or name uniqueness.



package main

import ( "fmt" "github.com/go-playground/validator/v10" "unicode")

func passwordValidator(fl validator.FieldLevel) bool { pwd := fl.Field().String() hasUpper := false hasDigit := false for _, ch := range pwd { if unicode.IsUpper(ch) { hasUpper = true } if unicode.IsDigit(ch) { hasDigit = true } } return len(pwd) >= 8 && hasUpper && hasDigit}

type Account struct { Password string `validate:"password"`}

func main() { validate := validator.New() validate.RegisterValidation("password", passwordValidator)

acc := Account{Password: "weak"} err := validate.Struct(acc) if err != nil { fmt.Println("Password did not pass validation") } else { fmt.Println("Password is valid") }}


4. Validating HTTP requests with Gin

The Gin framework uses

Recommendations