generated from VLADIMIR/template
clear
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
---
|
||||
name: create-go-module
|
||||
description: Создаёт Go-модуль в internal/modules/<snake_case>/ по конвенциям репозитория — обязательный interface.go с интерфейсом (имя начинается с I) и всеми публичными типами, в папке как минимум одна реализация интерфейса (неэкспортируемая структура + конструктор New*, возвращающий интерфейс). Загружай при создании нового модуля или заготовки модуля.
|
||||
whenToUse: Пользователь просит создать модуль/компонент/сервис/заготовку в 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`.
|
||||
|
||||
## Обязательные правила
|
||||
|
||||
1. **Папка модуля** — `internal/modules/<snake_case>/` (например, `email_sender`). Имя Go-пакета равно имени папки. Никаких вложенных подпакетов внутри модуля.
|
||||
2. **Файл `interface.go` обязателен.** В нём живёт ВЕСЬ публичный контракт модуля:
|
||||
- интерфейс(ы) модуля;
|
||||
- публичные типы: структуры-данные (DTO), перечисления, константы, именованные ошибки.
|
||||
Ничего другого (реализация, приватные хелперы) в этом файле нет.
|
||||
3. **Имя интерфейса начинается с `I`** — `I<CamelCase>`, например `IEmailSender`, `IPasswordGenerator`, `ICleaner`, `IStory`. Интерфейс без префикса `I` — недопустимо. В интерфейсе — только сигнатуры методов, без полей.
|
||||
4. **Реализация — в отдельном файле** (например, `<короткое_имя>.go` или `service.go`): неэкспортируемая структура (строчная, например `type emailSender struct`), методы которой реализуют интерфейс, и конструктор `func New<CamelCase>(...) I<CamelCase>`, возвращающий **интерфейс**, а не структуру.
|
||||
5. **В папке модуля — как минимум одна реализация интерфейса.** Модуль не может состоять из одного `interface.go`: рядом с ним всегда лежит неэкспортируемая структура, реализующая `I<CamelCase>` (см. правило 4), и конструктор, возвращающий интерфейс. Если реализаций несколько — каждая в своём файле.
|
||||
6. **Сигнатуры методов**: операции с внешним миром (сеть, файлы, БД, таймеры) принимают `context.Context` первым аргументом и возвращают `error`; чистые вычисления — без контекста (пример: `Generate() (string, error)` у `password_generator`).
|
||||
7. **Комментарии — на русском.** Каждый публичный идентификатор имеет doc-комментарий, начинающийся с имени символа. Пояснения сложных мест — тоже по-русски.
|
||||
8. **Ошибки** оборачиваются через `fmt.Errorf("<snake_case>: ...: %w", err)` — префикс с именем модуля.
|
||||
9. **JSON-теги** у сериализуемых структур — `json:"..."` (эталон: `storytelling/interface.go`).
|
||||
10. **Зависимости между модулями**: вместо импорта чужого модуля объявляется минимальный локальный интерфейс в файле `dependency.go` (эталон: `internal/modules/storytelling/dependency.go` объявляет собственный `ICleaner`). Это исключает циклические импорты и связывает модули только через их интерфейсы.
|
||||
11. **Тесты** — для модуля желателен файл `*_test.go` рядом с реализацией (примеры: `email_sender/sender_test.go`, `cleaner/service_test.go`).
|
||||
|
||||
## Шаги
|
||||
|
||||
1. **Определи имя модуля.** Если имя неоднозначно — уточни у пользователя. Приведи имя к двум формам:
|
||||
- snake_case — папка и пакет: «генератор паролей» → `password_generator`;
|
||||
- CamelCase — имена типов и интерфейса: `PasswordGenerator` → `IPasswordGenerator`.
|
||||
2. **Создай папку** `internal/modules/<snake_case>/`.
|
||||
3. **Напиши `interface.go`** (обязательно): сначала публичные типы/константы, затем интерфейс `I<CamelCase>`.
|
||||
4. **Напиши файл(ы) реализации** (обязательно, минимум один) — неэкспортируемая структура + конструктор `New<CamelCase>(...) I<CamelCase>`.
|
||||
5. **При необходимости** добавь `dependency.go` (локальные интерфейсы зависимостей) и `*_test.go`.
|
||||
6. **Проверь сборку** из корня проекта: `go build ./...` и `go vet ./...`. Ошибки — исправь.
|
||||
|
||||
## Шаблон interface.go
|
||||
|
||||
```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
|
||||
}
|
||||
```
|
||||
|
||||
## Шаблон реализации
|
||||
|
||||
```go
|
||||
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 ./...` проходят без ошибок.
|
||||
Reference in New Issue
Block a user