TGViewer
Библиотека Go-разработчика | Golang Библиотека Go-разработчика | Golang @goproglib · 24.1K subscribers
Post #7213 3.28K
👨‍💻 Скрытая цена чрезмерной абстракции в Go

Интерфейсы повсюду, многослойные пакеты, DI-контейнеры, generic-репозитории. Код выглядит солидно на ревью. Но стоит починить баг, и вы проходите шесть слоёв абстракции ради пяти строк логики. В Go это обходится дороже, чем кажется.

Почему это происходит

Интерфейсы в Go не требуют implements, любой тип удовлетворяет им неявно. Это удобно, но создаёт ловушку. Интерфейсы легко определять, поэтому их определяют слишком много. Пакеты легко создавать, поэтому кодовая база обрастает слоями ради диаграммы, а не ради задачи.

Чем это бьёт

Вы видите s.repo.Find(ctx, query.NewUserQuery().WithID(id)) и не знаете, это база, кэш или мок. Индирекция без пользы, просто шум. Интерфейсы создаются под единственную реализацию ещё до первого теста. Тесты обрастают моками для моков. Файл теста длиннее кода, который он тестирует.

Как оставаться простыми

Начинайте с конкретики. Напишите структуру, заставьте работать. Интерфейс выносите, когда появится вторая реализация. Так устроена стандартная библиотека Go. io.Reader не определили заранее:
type UserStore struct {
db *sql.DB
}

func (s *UserStore) GetByID(ctx context.Context, id string) (*User, error) {
// реальная реализация
}

// Интерфейс только когда нужен
type UserGetter interface {
GetByID(ctx context.Context, id string) (*User, error)
}


Пакеты должны делать, а не транслировать. Если пакет только переводит между другими пакетами, это шов без назначения. Для большинства сервисов плоская структура cmd/, internal/store/, internal/api/ работает лучше.

Функции вместо интерфейсов, где уместно. Не каждое поведение нужно выражать через интерфейс:
func SendWelcome(ctx context.Context, user User, send func(context.Context, string, string) error) error {
return send(ctx, user.Email, welcomeMessage(user))
}


Называйте по действию, а не по слою. UserActivator, SessionIssuer, PasswordResetter вместо UserService, UserManager, UserHandler. Точность в имени сопротивляется желанию сваливать всё в одну абстракцию.

Простой симптом. Если для одной фичи вы трогаете интерфейс, структуру, конструктор, мок и фикстуру до написания логики, архитектура работает против вас.

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoDeep
  • 👍 13
  • 🌚 7
  • 🥱 3
  • 😁 2
  • ❤ 1
More from @goproglib
  1. Sep 30, 2026🧑‍💻 Эмулятор AWS-сервисов Kumo — это небольшой инструмент на Go для локальной имитации A…
  2. Sep 29, 2026👨‍💻 Библиотека для написания LSP-серверов Написать свой Language Server с нуля на Go сло…
  3. Sep 28, 2026🤔 Вопрос с собеседования по Go Что выведет программа? ❤️ — 1 true / 0 false 🔥 — 1 true /…
  4. Sep 28, 2026👩‍💻 Что на самом деле происходит внутри Go map? После Go 1.24 обычный map внутри работае…
  5. Sep 26, 2026🔥 В Go 1.27 появился portable SIMD До этого SIMD-оптимизации в Go требовали архитектурног…
  6. Sep 25, 2026🤡🤡 📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека Go-разработчика #GoGiggle
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →