package.json مقابل go.mod: أين اختفى حقل الإصدار؟
إذا انتقلت من JavaScript إلى Go، فسيُفاجئك أمر واحد.
افتح ملف package.json. سترى حقل الإصدار (version) في الأعلى تماماً. من السهل قراءته، ويمكنك تغييره في طلب سحب (pull request). إنه موجود داخل الكود الخاص بك.
الآن افتح ملف go.mod.
الإصدار ليس موجوداً هناك. هذا ليس خطأً، بل هو خيار.
لا تستخدم Go حقل إصدار للموديول (module) الخاص بك، بل تستخدم وسوم git (git tags) بدلاً من ذلك.
كيف يعمل الأمر:
• تقوم بتشغيل git tag v1.2.3
• تقوم بدفع (push) الوسم إلى المستودع (repository) الخاص بك
• يصبح هذا الوسم هو إصدارك
عندما يقوم شخص ما بتشغيل go get ، تبحث Go في وسوم git الخاصة بك للعثور على الالتزام (commit) الصحيح. الوسم هو المصدر الوحيد للحقيقة.
يتميز هذا التصميم بنقطة قوة رئيسية؛ حيث لا يمكن للإصدار أن يشير أبداً إلى الكود الخاطئ. في npm، يمكن أن ينفصل الكود المنشور عن حقل الإصدار. أما في Go، فهما الشيء نفسه؛ الإصدار هو الالتزام (commit).
ومع ذلك، فإن هذا يغير سير عملك (workflow):
- الرؤية (Visibility): لا يمكنك رؤية إصدارك بمجرد النظر إلى ملف؛ بل يجب عليك تشغيل أمر git للعثور عليه.
- مراجعة الكود (Code Reviews): لا يظهر رفع الإصدار (version bump) في مقارنة الكود (code diff)؛ لأنه عبارة عن دفع وسم (tag push) وليس تغييراً في الكود.
- البناء المحلي (Local Builds): الالتزام (commit) بدون وسم يظهر إصداراً وهمياً (pseudo-version) غير مرتب. لن تحصل على إصدار نظيف إلا بعد وضع وسم للالتزام.
- الإصدارات الرئيسية (Major Versions): هذا هو التغيير الأكبر. في Go، يجب أن تتضمن الإصدارات v2 وما فوق الإصدار في مسار الاستيراد (import path).
مثال:
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.
إذا كنت تفتقد تجربة npm، يمكنك حقن الإصدار في الملف الثنائي (binary) الخاص بك أثناء وقت البناء باستخدام ldflags. يتيح ذلك لتطبيقك الاستجابة لأمر الإصدار.
المقايضة بسيطة: حقل الإصدار سهل القراءة والمراجعة، لكنه قد يكذب. وسم git يصعب رؤيته، لكنه دائماً صادق.
اختارت Go الحقيقة على الراحة.
إلى مطوري Go: هل هذا هو النموذج الأفضل؟ هل تفضلون وجود حقل إصدار في go.mod إذا كانت الأدوات تتحقق منه مقابل وسم git؟
المصدر: https://dev.to/dalirnet/packagejson-vs-gomod-where-did-the-version-field-go-3301