Files
evening_detective_server/.dsh/skills/create-go-module/SKILL.md
T
2026-08-21 00:09:32 +07:00

8.1 KiB
Raw Blame History

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.

Обязательные правила

  1. Папка модуляinternal/modules/<snake_case>/ (например, email_sender). Имя Go-пакета равно имени папки. Никаких вложенных подпакетов внутри модуля.
  2. Файл interface.go обязателен. В нём живёт ВЕСЬ публичный контракт модуля:
    • интерфейс(ы) модуля;
    • публичные типы: структуры-данные (DTO), перечисления, константы, именованные ошибки. Ничего другого (реализация, приватные хелперы) в этом файле нет.
  3. Имя интерфейса начинается с II<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 — имена типов и интерфейса: PasswordGeneratorIPasswordGenerator.
  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

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 ./... проходят без ошибок.