Go: типы и проверка значений на границе
Выражайте устойчивую структуру данными struct и конкретными типами. Разные предметные идентификаторы при реальном риске смешения могут иметь отдельные defined types; тип не заменяет runtime-проверку входа.
Плохо
type UserID = string
type OrderID = string
// Оба alias остаются string: случайная подмена компилируется.
Хорошо
type UserID string
type OrderID string
type Assignment struct {
OrderID OrderID
OwnerID UserID
}
Почему это важно
Defined type отличается от underlying type; alias лишь дает прежнему типу другое имя. Compiler предотвращает часть случайных присваиваний, но явное преобразование и пустое значение остаются возможными. Для ID из JSON нужны отдельные проверки формата, существования и полномочий.
Когда применять
Для Go domain/API boundaries. Конкретный struct предпочтителен map[string]any, если поля известны; any допустим для действительно открытой структуры с дальнейшим type switch/проверкой. Не создавайте interface без потребителя: маленький интерфейс описывает нужное поведение, а не зеркалирует все методы реализации. Для отсутствия/ошибки определите nil, ok или error явно, не смешивайте с допустимым нулем.
Учитывайте zero value: nil map читается, но запись требует инициализации; nil slice допускает append. Interface с typed nil pointer не равен nil interface — это важно при возврате error. Не утверждайте, что named integer автоматически ограничивает диапазон или overflow; размер int зависит от платформы, для wire/storage выберите явный контракт ширины/диапазона. Для длительности используйте time.Duration с единицами, для денег — отдельный точный профиль.
Generics вводятся для повторяющегося типобезопасного алгоритма, когда это упрощает потребителей; они не являются обязательным слоем каждого DTO. Возможности языка и синтаксис должны соответствовать go directive проекта. Пример — декларации внутри пакета, не законченный валидатор ID.
Кто что делает
Человек
Определяет семантику типов, допустимые нулевые значения и границы валидации.
AI-агент
Различает alias/defined type, проверяет nil и диапазоны; не подменяет runtime-проверку компиляцией.
Как проверить у себя
-
Значения OrderID и UserID → обычное присваивание одному полю → корректный тип принимается, переменная другого defined type без conversion не компилируется → compile fixtures.
-
Пустой/неверный строковый ID проходит explicit conversion → boundary validator → отклонен по отдельному контракту → отрицательный runtime-тест проекта.
-
nil map/interface и нулевой числовой ввод → код соответствующей границы → нет неучтенного panic/ложного успеха, результат задокументирован → узкие edge tests.
Первоисточники
Дата проверки отражает содержательную сверку. Синхронизация сайта не обновляет её автоматически.