Теги полей структуры

Теги полей структуры (struct field tags) в Go - это строковые литералы, которые добавляются к объявлениям полей структуры. Они представляют собой метаданные, доступные во время выполнения через рефлексию. Теги позволяют аннотировать поля структуры для различных целей, таких как сериализация в JSON, XML, валидация данных, работа с базами данных и многое другое.

Тег записывается сразу после типа поля в обратных кавычках. Он состоит из пар ключ:значение, разделенных пробелами. Ключ указывает на библиотеку или пакет, который будет интерпретировать тег, а значение - это опция для этого пакета.

Синтаксис

gotype StructName struct {
  FieldName FieldType `key:"value" another:"value"`
}

Теги записываются в обратных кавычках (``) и представляют собой строку. Внутри строки могут быть пробелы, если они не являются частью ключа или значения. Каждый тег должен быть заключен в двойные кавычки.

Пример

Давайте создадим структуру User с тегами json и validate. Тег json определяет имя поля при сериализации в JSON, а тег validate указывает правило валидации:

gopackage main

import (
  "encoding/json"
  "fmt"
)

type User struct {
  ID  int  `json:"id"`
  Name  string `json:"name" validate:"required"`
  Email string `json:"email" validate:"email"`
}

func main() {
  user := User{
    ID:  1,
    Name:  "John Doe",
    Email: "john@example.com",
  }

  jsonData, _ := json.Marshal(user)
  fmt.Println(string(jsonData))
}

Результат выполнения кода:

go{"id":1,"name":"John Doe","email":"john@example.com"}

Как видите, имена полей в JSON соответствуют значениям тегов json, а не оригинальным именам полей структуры. Тег validate не используется стандартной библиотекой, но может быть обработан сторонней библиотекой валидации.

Пример

Теперь рассмотрим пример с тегом omitempty, который позволяет опускать пустые поля при сериализации в JSON:

gopackage main

import (
  "encoding/json"
  "fmt"
)

type Product struct {
  Name  string  `json:"name"`
  Price float64 `json:"price,omitempty"`
  Stock int   `json:"stock,omitempty"`
}

func main() {
  product := Product{
    Name: "Laptop",
  }

  jsonData, _ := json.Marshal(product)
  fmt.Println(string(jsonData))
}

Результат выполнения кода:

go{"name":"Laptop"}

Поля Price и Stock были опущены, потому что их значения являются нулевыми для соответствующих типов (0 для чисел), и мы использовали опцию omitempty в тегах.

Пример

Теги также могут использоваться для управления преобразованием данных при работе с базами данных. Например, с помощью тега db можно указать имя столбца в таблице:

gopackage main

import (
  "fmt"
  "reflect"
)

type Book struct {
  Title  string `db:"book_title"`
  Author string `db:"author_name"`
  Year   int  `db:"publication_year"`
}

func main() {
  book := Book{
    Title:  "The Go Programming Language",
    Author: "Alan Donovan",
    Year:   2015,
  }

  t := reflect.TypeOf(book)
  for i := 0; i < t.NumField(); i++ {
    field := t.Field(i)
    tag := field.Tag.Get("db")
    fmt.Printf("Field: %s, DB Tag: %s\n", field.Name, tag)
  }
}

Результат выполнения кода:

go"Field: Title, DB Tag: book_title"
"Field: Author, DB Tag: author_name"
"Field: Year, DB Tag: publication_year"

В этом примере мы используем пакет reflect для получения значений тегов db во время выполнения программы.

Смотрите также