generated from VLADIMIR/template
8.1 KiB
8.1 KiB
name, description, whenToUse
| name | description | whenToUse |
|---|---|---|
| create-go-module | Создаёт Go-модуль в internal/modules/<snake_case>/ по конвенциям репозитория — обязательный interface.go с интерфейсом (имя начинается с I) и всеми публичными типами, в папке как минимум одна реализация интерфейса (неэкспортируемая структура + конструктор New*, возвращающий интерфейс). Загружай при создании нового модуля или заготовки модуля. | Пользователь просит создать модуль/компонент/сервис/заготовку в internal/modules, либо «сделать по конвенциям проекта», либо явно упоминает interface.go или интерфейс с префиксом I. |
Создание Go-модуля (internal/modules)
Контекст
В этом проекте переиспользуемые компоненты живут в internal/modules/<имя>/ — по одному модулю на папку. Публичный контракт модуля описывается в обязательном файле interface.go. Эталонные примеры действующих модулей: internal/modules/password_generator, internal/modules/email_sender, internal/modules/cleaner, internal/modules/storytelling, internal/modules/processor_jwt.
Обязательные правила
- Папка модуля —
internal/modules/<snake_case>/(например,email_sender). Имя Go-пакета равно имени папки. Никаких вложенных подпакетов внутри модуля. - Файл
interface.goобязателен. В нём живёт ВЕСЬ публичный контракт модуля:- интерфейс(ы) модуля;
- публичные типы: структуры-данные (DTO), перечисления, константы, именованные ошибки. Ничего другого (реализация, приватные хелперы) в этом файле нет.
- Имя интерфейса начинается с
I—I<CamelCase>, напримерIEmailSender,IPasswordGenerator,ICleaner,IStory. Интерфейс без префиксаI— недопустимо. В интерфейсе — только сигнатуры методов, без полей. - Реализация — в отдельном файле (например,
<короткое_имя>.goилиservice.go): неэкспортируемая структура (строчная, напримерtype emailSender struct), методы которой реализуют интерфейс, и конструкторfunc New<CamelCase>(...) I<CamelCase>, возвращающий интерфейс, а не структуру. - В папке модуля — как минимум одна реализация интерфейса. Модуль не может состоять из одного
interface.go: рядом с ним всегда лежит неэкспортируемая структура, реализующаяI<CamelCase>(см. правило 4), и конструктор, возвращающий интерфейс. Если реализаций несколько — каждая в своём файле. - Сигнатуры методов: операции с внешним миром (сеть, файлы, БД, таймеры) принимают
context.Contextпервым аргументом и возвращаютerror; чистые вычисления — без контекста (пример:Generate() (string, error)уpassword_generator). - Комментарии — на русском. Каждый публичный идентификатор имеет doc-комментарий, начинающийся с имени символа. Пояснения сложных мест — тоже по-русски.
- Ошибки оборачиваются через
fmt.Errorf("<snake_case>: ...: %w", err)— префикс с именем модуля. - JSON-теги у сериализуемых структур —
json:"..."(эталон:storytelling/interface.go). - Зависимости между модулями: вместо импорта чужого модуля объявляется минимальный локальный интерфейс в файле
dependency.go(эталон:internal/modules/storytelling/dependency.goобъявляет собственныйICleaner). Это исключает циклические импорты и связывает модули только через их интерфейсы. - Тесты — для модуля желателен файл
*_test.goрядом с реализацией (примеры:email_sender/sender_test.go,cleaner/service_test.go).
Шаги
- Определи имя модуля. Если имя неоднозначно — уточни у пользователя. Приведи имя к двум формам:
- snake_case — папка и пакет: «генератор паролей» →
password_generator; - CamelCase — имена типов и интерфейса:
PasswordGenerator→IPasswordGenerator.
- snake_case — папка и пакет: «генератор паролей» →
- Создай папку
internal/modules/<snake_case>/. - Напиши
interface.go(обязательно): сначала публичные типы/константы, затем интерфейсI<CamelCase>. - Напиши файл(ы) реализации (обязательно, минимум один) — неэкспортируемая структура + конструктор
New<CamelCase>(...) I<CamelCase>. - При необходимости добавь
dependency.go(локальные интерфейсы зависимостей) и*_test.go. - Проверь сборку из корня проекта:
go build ./...иgo vet ./.... Ошибки — исправь.
Шаблон interface.go
package <snake_case>
import "context"
// <TypeName> — описание публичного типа.
type <TypeName> struct {
Field string `json:"field"`
}
// I<CamelCase> — контракт модуля <snake_case>.
type I<CamelCase> interface {
// <Method> — описание метода.
<Method>(ctx context.Context, in <TypeName>) error
}
Шаблон реализации
package <snake_case>
import (
"context"
"fmt"
)
// <lowerCamelCase> — реализация I<CamelCase>.
type <lowerCamelCase> struct {
// внутренние поля
}
// New<CamelCase> создаёт реализацию I<CamelCase>.
func New<CamelCase>(...) I<CamelCase> {
return &<lowerCamelCase>{}
}
func (s *<lowerCamelCase>) <Method>(ctx context.Context, in <TypeName>) error {
// TODO: реализация
return fmt.Errorf("<snake_case>: не реализовано")
}
Критерии готовности
- Папка
internal/modules/<snake_case>/создана, имя пакета равно имени папки. interface.goсуществует; все публичные типы, константы и интерфейсы описаны именно в нём.- Имя интерфейса начинается с
I. - В папке модуля есть как минимум одна реализация интерфейса (неэкспортируемая структура + конструктор).
- Реализация неэкспортируемая; конструктор возвращает интерфейс, а не структуру.
- doc-комментарии на русском у всех публичных идентификаторов.
go build ./...иgo vet ./...проходят без ошибок.