𝗣𝗮𝗰𝗸𝗮𝗴𝗲.𝗷𝘀𝗼𝗻 проти 𝗚𝗼.𝗺𝗼𝗱: куди зникло поле версії?
Якщо ви переходите з JavaScript на Go, одна річ вас здивує.
У файлі package.json версія знаходиться прямо зверху. Ви можете її прочитати. Ви можете змінити її в pull request. Ви можете її знайти. Це факт, який живе безпосередньо у вашому коді.
Тепер відкрийте файл go.mod. Версії там немає.
Це не помилка. Це свідомий вибір.
Go не використовує поле версії для вашого власного модуля. Замість цього Go використовує git tags.
Щоб встановити версію в Go, потрібно зробити наступне:
- git tag v1.2.3
- git push origin v1.2.3
Git tag є єдиним джерелом істини. Коли хтось запускає go get, Go шукає теги у вашому репозиторії, щоб знайти потрібний коміт.
Ця архітектура має велику перевагу. Версія ніколи не може вказувати на неправильний код. В npm опублікований код і тегований вихідний код можуть розходитися. В Go це одне й те саме, оскільки версія є вказівником на коміт.
Однак це змінює ваш робочий процес у кількох аспектах:
- Пошук версії потребує команди. Вам доведеться запускати
git describe --tagsзамість того, щоб просто зазирнути у файл. - Оновлення версій не відображаються в code reviews. Пуш тегу не є зміною коду, тому він не з'являється в pull request.
- Локальні збірки використовують псевдоверсії. Поки ви не поставите тег на коміт, замість чистої версії на кшталт
v1.2.3ви бачитимете довгий рядок із цифр та хешів. - Мажорні версії змінюють шлях імпорту. В npm ви змінюєте номер версії, але зберігаєте назву пакета. В Go версії
v2і вище вимагають зміни шляху, наприклад, на/v2. Це дозволяє програмі одночасно використовуватиv1таv2однієї й тієї ж бібліотеки без конфліктів.
Більшість інших екосистем зберігають версію у файлі:
- Node:
package.json - Rust:
Cargo.toml - Python:
pyproject.toml - Java:
pom.xml - .NET:
.csproj
Go працює інакше. Він покладається лише на git tags.
Якщо ви хочете, щоб ваш Go-бінарний файл показував чисту версію, ви можете впровадити її під час процесу збірки за допомогою ldflags. Багато розробників також використовують такі інструменти, як goreleaser, щоб автоматизувати процес тегування та релізів.
Ці дві моделі представляють різні пріоритети:
- Версії на основі файлів легко читати та перевіряти. Ризик полягає в тому, що файл може розійтися з фактичним кодом.
- Версії на основі тегів неможливо підробити. Ціна цього — їх важче побачити та керувати ними.
Go обрав модель тегів, щоб гарантувати, що маніфест завжди відповідає коду.
Для тих, хто випускає Go-код: як модель, що базується лише на тегах, відчувається у вашій щоденній роботі? Чи змінили б ви її?
Джерело: https://dev.to/dalirnet/packagejson-vs-gomod-where-did-the-version-field-go-3301