TGStat
TGStat
Qidiruv uchun matnni kiriting
Ilg‘or kanal qidiruvi
  • flag Uzbek
    Sayt tili
    flag Russian flag English flag Uzbek
  • Saytga kirish
  • Katalog
    Kanal va guruhlar katalogi Hududiy to‘plamlar Tematik to‘plamlar Платные каналы Kanallar qidiruvi
    Kanal/guruh qo‘shish
  • Reytinglar
    Kanallar reytingi Guruhlar reytingi Postlar reytingi
    Brendlar va shaxslar reytingi
  • Analitika
  • Postlarda qidiruv
  • Telegram'ni kuzatish
  • Targ‘ibot
    Yandex Business orqali reklama TGStat Agency orqali kanallarda reklama TGStat.ru saytida reklama
myStack

22 Mar 2025, 19:36

Telegram'da ochish Ulashish Shikoyat qilish

📦 pkg directory considered harmful

🚫 Почему не стоит держать код приложения вне директории internal

Чтобы понять, в чём проблема, нужно разобраться с понятием «публичный интерфейс». Я уже писал статью, где постарался понятно объяснить, что это такое и почему термин «интерфейс» часто вызывает путаницу (из-за перегруженности термина). С ней можно ознакомиться тут. В этом тексте речь идёт именно о публичном интерфейсе, а не о типе данных interface!

При проектировании публичных интерфейсов важно понимать:
🔒их нельзя менять без необходимости — иначе сломаются клиенты, которые от них зависят (комикс на тему). То есть нужно сохранять обратную совместимость. По этой причине приложения версионируют (см. https://semver.org/lang/ru/) и ломают обратную совместимость только в мажорных релизах (MAJOR.minor.patch), которые выходят намного реже, чем minor и patch. Чтобы не приходилось часто выпускать мажорные релизы, интерфейс нужно тщательно продумывать и делать минимальным (минимально необходимым).

📌 Например, в HTTP API это означает, что не стоит создавать несколько эндпоинтов для похожих действий. Вместо /users/active и /users/inactive лучше сделать один — /users?status=active|inactive.

Публичным интерфейсом может быть не только HTTP API, но и код, от которого зависят другие приложения. И этот интерфейс также необходимо делать минимально возможным, потому что всё, что мы однажды сделали публичным, — обязаны поддерживать.

🚧 Защита кода с помощью internal
Чтобы исключить возможность того, что другие приложения будут зависеть от нашего кода, нужно запретить этот код импортировать. Для этих целей в Go 1.4 появилась директория internal, которая запрещает импортировать то, что внутри нее любому коду на уровень выше (в том числе из другого репозитория).
📖 Подробнее про internal - в документации.

🤡 Но часто этой директории придают другие значения — например, «в internal кладём бизнес-логику, а в pkg — библиотеки». Это ошибочное представление, которое возникло из-за исторических причин, а сейчас распространено т.к. бездумно копируется. На самом деле любые трактовки internal, отличные от официальной, понятны только тем, кто их придумал. Если использовать internal по назначению, то в нее попадает код, который мы запрещаем импортировать, а вне internal остается код, который разрешаем импортировать, а никакой не "бизнес код", не "код, который должен стать библиотекой в дальнейшем" и т.д. Если есть код, который планируется в будущем сделать библиотекой, но сейчас еще не пришло время для этого, то можно его поместить внутри internal, например, создав уже там директорию pkg.

Часто в pkg хранят "клиенты" от http или gRPC API приложения, и хоть это удобно, но архитектурно это уязвимо. Внутри этих клиентов код часто использует пакеты самого приложения (со структурами например), поэтому импортируя этот клиент, неявно импортируются и другие пакеты. Правильнее хранить клиенты в отдельном репозитории и использовать "свои" структуры (определенные в репозитории клиента). А не свои и не получится т.к. в основном приложении они будут лежать в internal!

🔗 Полезные ссылки:
- https://eli.thegreenplace.net/2019/simple-go-project-layout-with-modules/ (последний абзац)
- https://medium.com/golang-learn/go-project-layout-e5213cdcfaa2
- https://go.dev/doc/modules/layout — хорошая статья от команды Go про структуру проектов. Я считаю, что она должна быть основой, которую надо читать на эту тему, а не распиаренный golang-standards/project-layout (который, вопреки названию, не является стандартом).

🗂 Какую структуру использовать
В большинстве случаев Go-проект содержит всего две директории с го кодом:
- cmd с main.go
- internal - со всем остальным кодом

Как организовать содержимое внутри internal — зависит от многого. Я считаю идеи чистой архитектуры полезными и делаю свой репозиторий, где стараюсь следовать этим принципам:
📎 https://github.com/rostislaved/go-clean-architecture

1.9k 4 34 71 15
Katalog
Kanal va guruhlar katalogi Kanallar to‘plamlari Kanallar qidiruvi Kanal/guruh qo‘shish
Reytinglar
Telegram-kanallar reytingi Telegram-guruhlar reytingi Postlar reytingi Brendlar va shaxslar reytingi
API
Statistika API'si Postlar qidiruvi API'si API Callback
Kanallarimiz
@TGStat @TGStat_Chat @telepulse @TGStatAPI
O‘qish
Академия TGStat Telegram tadqiqoti 2019 Telegram tadqiqoti 2021 Telegram tadqiqoti 2023
Kontaktlar
Справочный центр Qo‘llab-quvvatlash Email Vakansiyalar
Har xil narsalar
Foydalanuvchi shartnomasi Maxfiylik siyosati Ommaviy oferta
Botlarimiz
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot