Data Validation in Go (Golang): Libraries, Approaches, and Code Examples

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): A Complete Guide to Libraries and Approaches



Data validation is a critical part of any web application, API, or microservice. In Go (Golang), this task is handled both by standard tools and powerful third-party libraries. In this article, we will cover the main approaches, popular libraries, and provide practical code examples.



Why is validation needed in Go?

Go is a strongly typed language, which already provides some protection against incorrect data. However, types do not check business rules: an email must contain "@", age must be in the range 0–120, a password must have a minimum length. Without validation, you risk getting:

  • SQL injections and XSS attacks
  • Incorrect data in the database
  • Unexpected panics and runtime errors


Built-in validation tools

The simplest validation is done "manually" in functions. Example:

type User struct {    Name  string    Email string    Age   int}

func ValidateUser(u User) error { if u.Name == "" { return errors.New("name is required") } if !strings.Contains(u.Email, "@") { return errors.New("invalid email") } if u.Age < 0 || u.Age > 150 { return errors.New("age must be between 0 and 150") } return nil}

This approach is simple, but for complex structures it becomes cumbersome and hard to maintain. Therefore, the Go community has created specialized libraries.



1. go-playground/validator — the de facto standard

Link: github.com/go-playground/validator/v10

This is the most popular validation library in Go (over 15k stars on GitHub). It uses struct tags for declarative rule descriptions.



Installation

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


Usage example

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=0,lte=150"` Password string `validate:"required,min=8"`}

func main() { validate := validator.New()

user := User{ Name: "A", Email: "not-email", Age: 200, Password: "123", }

err := validate.Struct(user) if err != nil { for _, e := range err.(validator.ValidationErrors) { fmt.Printf("Field: %s, Rule: %s, Value: %v", e.Field(), e.Tag(), e.Value()) } }}


Output:

Field: Name, Rule: min, Value: AField: Email, Rule: email, Value: not-emailField: Age, Rule: lte, Value: 200Field: Password, Rule: min, Value: 123


Popular tag rules

  • required — field is mandatory
  • min, max — for numbers and strings
  • len — exact length
  • email — email validation
  • url — URL validation
  • gte, lte — greater than/less than or equal
  • oneof — one of the values (oneof=admin user)


Custom validators

validate.RegisterValidation("is-odd", func(fl validator.FieldLevel) bool {    return fl.Field().Int()%2 != 0})

type MyStruct struct { Number int `validate:"is-odd"`}


2. ozzo-validation — an alternative with chains

Link: github.com/go-ozzo/ozzo-validation/v4

This library offers a more "Go-idiomatic" approach: rules are defined through functions rather than tags. This provides greater flexibility and readability.



Example

package main

import ( "fm

Recommendations