Как в Go реализовать хранение данных разных типов в одной переменной (аналог Union)?

Ответ

В Go нет прямого аналога примитива union из таких языков, как C/C++. Вместо этого для хранения значений разных типов используется пустой интерфейс any (в версиях до Go 1.18 — interface{}).

any может содержать значение любого типа. Чтобы работать с конкретным типом, используется механизм проверки типа (type assertion) или switch по типу.

Пример с switch:

func printValue(v any) {
    switch val := v.(type) {
    case int:
        fmt.Printf("Это целое число: %dn", val)
    case string:
        fmt.Printf("Это строка: %sn", val)
    case bool:
        fmt.Printf("Это булево значение: %tn", val)
    default:
        fmt.Println("Неизвестный тип")
    }
}

Основные сценарии использования:

  • Обработка данных неизвестного типа: Например, при декодировании JSON или данных из базы, где поле может иметь разный тип.
  • Создание гетерогенных коллекций: Слайсы или мапы, которые могут хранить элементы разных типов.
  • Реализация полиморфного поведения без строгой привязки к общему интерфейсу.

Важно: Чрезмерное использование any снижает типобезопасность и читаемость кода, так как проверки типов переносятся из времени компиляции во время выполнения. С появлением дженериков в Go 1.18 для создания типобезопасных функций и структур данных, работающих с разными типами, предпочтительнее использовать именно их.