package.json מול go.mod: לאן נעלם שדה הגרסה?

אם תעברו מ-JavaScript ל-Go, דבר אחד יפתיע אתכם.

פתחו קובץ package.json. תראו שדה version ממש למעלה. קל לקרוא אותו. ניתן לשנות אותו ב-pull request. הוא נמצא בתוך הקוד שלכם.

עכשיו פתחו קובץ go.mod.

הגרסה לא נמצאת שם. זו לא טעות. זו בחירה.

Go לא משתמשת בשדה גרסה עבור המודול שלכם. במקום זאת, היא משתמשת ב-git tags.

איך זה עובד: • מריצים git tag v1.2.3 • דוחפים (push) את ה-tag למאגר (repository) שלכם • ה-tag הזה הופך לגרסה שלכם

כשמישהו מריץ go get, Go בודקת את ה-git tags שלכם כדי למצוא את ה-commit המתאים. ה-tag הוא המקור היחיד לאמת (single source of truth).

לתכנון הזה יש יתרון משמעותי. גרסה לעולם לא יכולה להצביע על הקוד הלא נכון. ב-npm, הקוד שפורסם ושדה הגרסה יכולים להשתנות ולהיפרד זה מזה. ב-Go, הם אותו הדבר. הגרסה היא ה-commit.

עם זאת, זה משנה את זרימת העבודה (workflow) שלכם:

דוגמה: v1 משתמשת ב-github.com/you/my-app v2 משתמשת ב-github.com/you/my-app/v2

זה מאפשר לתוכנית אחת להשתמש בשתי גרסאות ראשיות שונות של אותה ספרייה ללא התנגשות.

רוב השפות האחרות שומרות את הגרסה בקובץ: • Node: package.json • Rust: Cargo.toml • Python: pyproject.toml • Java: pom.xml

Go היא החריגה. היא מסתמכת אך ורק על git tags.

אם אתם מתגעגעים לחוויית ה-npm, תוכלו להזריק את הגרסה לתוך ה-binary שלכם בזמן הבנייה (build time) באמצעות ldflags. זה מאפשר לאפליקציה שלכם להגיב לפקודת גרסה.

הפשרה (trade-off) היא פשוטה: שדה גרסה הוא קל לקריאה ולסקירה, אך הוא עלול לשקר. git tag הוא קשה לזיהוי, אך הוא תמיד אמת.

Go בחרה באמת על פני נוחות.

למפתחי Go: האם זה המודל הטוב ביותר? האם הייתם מעדיפים שדה גרסה ב-go.mod אם הכלים היו מאמתים אותו מול ה-git tag?

מקור: https://dev.to/dalirnet/packagejson-vs-gomod-where-did-the-version-field-go-3301