Help us shape the future of Go! Take the 2026 Go Developer Survey

nameform

package
v1.16.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

Documentation

Overview

Package nameform несёт ЕДИНСТВЕННУЮ форму имени ресурса Kachō и чистый предикат к ней — без транспорта.

Зачем отдельный пакет, а не константа рядом с валидаторами. Форма нужна и слою домена (self-validating newtype), а домену запрещено тянуть транспорт: правило чистой архитектуры — `domain/` только stdlib и контракты, без grpc (`architecture.md`). Валидаторы же обязаны возвращать готовый gRPC-статус, поэтому `pkg/validate` импортирует grpc — и импорт ЛЮБОГО его символа тянет grpc в граф зависимостей импортёра целиком: в Go зависимость пакетная, а не посимвольная.

Отсюда разделение: здесь — форма и предикат (ноль зависимостей вне stdlib), в `pkg/validate` — отказы в форме gRPC-статуса поверх этого предиката. Обе стороны читают ОДНУ строку, поэтому разойтись им не на чем.

Index

Constants

View Source
const ConstraintSuffix = "_name_check"

ConstraintSuffix — суффикс имени ограничения таблицы, которым форма имени продублирована на уровне базы.

Значение не выдумано здесь: имя ограничения строится как `<таблица> || '_name_check'` — одинаково в ШЕСТИ схемах, принявших канон формы имени (vpc, compute, storage, nlb, geo, iam). Согласие этой константы с миграциями держит гейт продукта internal/repohygiene TestNameFormConstraintSuffixMatchesMigrations: разойдись они — и отображение ошибки перестало бы узнавать ограничение, а «сервис пропустил негодное имя» снова читалось бы как «виноват ваш ввод».

Файл миграции здесь НЕ называется, и это не небрежность. Прежняя редакция называла `715001_resource_name_single_form.sql` — верно для пяти схем и неверно для шестой: цепь iam сведена в одну первичную миграцию, ограничение стоит в ней. Координата, верная для части популяции, посылает читателя не туда у остальной; какие схемы приняли канон и откуда, гейт ВЫВОДИТ из содержимого миграций и печатает переписью на каждом прогоне.

View Source
const Form = `^[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])?$`

Form — единственная форма имени ресурса в дереве: DNS label по RFC 1123.

Строчные латинские буквы, цифры и дефис; первый и последний символ — буква или цифра; длина 1..63. Производных «как общий, но здесь ещё подчёркивание» не заводится: два имени одного правила расходятся молча — так и разошлись четыре прежних валидатора (заглавные у одного, подчёркивание у двух, пустая строка у трёх), давая один контракт и разное исполнение (задача #715).

Форма взята внешним стандартом намеренно. Имя, годное как DNS label, годится сегментом адреса, меткой в средствах наблюдения и именем в конфигурации развёртывания — без экранирования и без второго правила «а здесь можно иначе». Спор о вкусах при заведении следующего ресурса снят: форма не наша.

Единственность объявления держит гейт internal/repohygiene TestResourceNameFormIsDeclaredOnce.

View Source
const MaxLen = 63

MaxLen — верхняя граница длины имени, та же, что в Form.

Variables

This section is empty.

Functions

func IsConstraint

func IsConstraint(table, constraint string) bool

IsConstraint отвечает, является ли ограничение `constraint` таблицы `table` тем самым дублем формы имени.

Зачем предикат вообще нужен

Ограничение формы — ЗАЩИТА ПОСЛЕДНЕГО РУБЕЖА, а не проверка ввода: форму имени сервис проверяет сам, до вставки (`validate.Name` / доменный newtype). Значит его срабатывание означает не «вызывающий прислал негодное имя», а «сервис пропустил негодное значение», — то есть НАШ дефект. Отображать такой отказ в `INVALID_ARGUMENT` значит обвинять вызывающего в чужой ошибке; ему место в фиксированном `INTERNAL` с записью в журнал.

Почему сравнение, а не суффикс

Проверка «имя кончается на ConstraintSuffix» короче и неверна: `users_display_name_check` в схеме iam кончается ровно так же, но сторожит длину другого поля в схеме, которой миграция 715001 не касалась. Точное сравнение с конструкцией миграции ошибиться не может, а имя таблицы Postgres сообщает в том же отказе (`pgconn.PgError.TableName`), поэтому дополнительных сведений вызывающему собирать не надо.

Пустые аргументы дают `false`: Postgres оставляет эти поля пустыми, когда отказ не про ограничение таблицы, и совпадение пустого с пустым было бы утверждением о форме имени там, где о ней речи не было.

func OK

func OK(value string) bool

OK сообщает, отвечает ли значение форме.

Пустая строка форме НЕ отвечает — и это верно на обоих путях, но означает разное: на правке пустое имя отвергается, на создании оно законный вход и до записи заменяется умолчанием. Решает это вызывающий; предикат отвечает только про форму.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL