Go's Secret Labels: What Are Struct Tags and Why You Need Them

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

Introduction: Magic Quotes in Go Code



If you've ever written Go structures for working with JSON, you've probably seen strange constructs like these:



type User struct {    Name string `json:"name"`    Age  int    `json:"age,omitempty"`}


These mysterious backticks (`json:"name"`) are called struct tags. For a beginner, they look like magic or unnecessary noise. But in reality, this is one of the most powerful and elegant features of Go, allowing meta-programming without complex macros.



In this article, we'll break down what struct tags are in Go, why they are needed, what types exist, and how to use them in real projects. You will stop fearing these "magic strings" and start using them consciously.



What Are Struct Tags? A Simple Explanation



Struct tags are string literals written after the field type in a structure. They are enclosed in backticks (`) and represent key:"value" pairs.



From the language's perspective, Go struct tags are just text. The Go compiler does not analyze or validate them. Their meaning only appears when you (or a library) read them via the reflect package.



Simply put: tags are metadata that you attach to struct fields. Other parts of your program can read this metadata and change their behavior.



Why Are Struct Tags Needed? 3 Main Scenarios



1. Serialization/Deserialization (JSON, XML, YAML)



This is the most common and understandable use case. Imagine you have a Go struct and you want to convert it to JSON (or vice versa).



type User struct {    ID        int    `json:"id"`    FirstName string `json:"first_name"`    LastName  string `json:"last_name"`    Password  string `json:"-"`}

func main() { user := User{ID: 1, FirstName: "Ivan", LastName: "Petrov", Password: "secret"} jsonData, _ := json.Marshal(user) fmt.Println(string(jsonData)) // Output: {"id":1,"first_name":"Ivan","last_name":"Petrov"} // The password is not included in the JSON because of the json:"-" tag}


Without tags, the fields would be named ID, FirstName, etc., which doesn't match JSON style (camelCase vs snake_case). Golang struct tags for JSON allow you to control:

  • The field name in JSON
  • Omitting empty fields (omitempty)
  • Excluding a field from output (-)
  • Nested options


2. Data Validation



Popular libraries like go-playground/validator use Go struct tags for validation. You simply write the rules directly in the struct:



type SignUpRequest struct {    Email    string `validate:"required,email"`    Password string `validate:"required,min=8,max=32"`    Age      int    `validate:"gte=18,lte=120"`}

func validateUser(user SignUpRequest) error { validate := validator.New() err := validate.Struct(user) return err}


This is incredibly convenient: validation rules are located next to the data, not scattered throughout the code. Struct tags for validation make the code self-documenting.



3. Working with Databases (ORM)



ORM libraries (GORM, Ent, SQLBoiler) actively use struct tags for ORM. For example, in GORM:



type Product struct {    gorm.Model    Code  string `gorm:"uniqueIndex;not null"`    Price uint   `gorm:"default:0"`    UserID uint  `gorm:"foreignKey:UserID"`}


The gorm tags define indexes, constraints, foreign keys, and other table settings. This eliminates the need to write separate migrations.



How Struct Tags Work

Blogs

Book Recommendations