𝗣𝗮𝗰𝗸𝗮𝗴𝗲.𝗷𝘀𝗼𝗻 𝗹𝘄𝗻 𝗚𝗼.𝗺𝗼𝗱: 𝗞𝗲 𝗺𝗮𝗻𝗮 𝗽𝗲𝗿𝗴𝗶𝗸𝗮𝗻𝘆𝗮 𝗺𝗲𝗱𝗮𝗻 𝘃𝗲𝗿𝘀𝗶?
Jika anda beralih daripada JavaScript ke Go, satu perkara akan mengejutkan anda.
Dalam fail package.json, versi berada tepat di bahagian atas. Anda boleh membacanya. Anda boleh mengubahnya dalam pull request. Anda boleh mencarinya. Ia adalah satu fakta yang wujud di dalam kod anda.
Sekarang buka fail go.mod. Versi tidak ada di sana.
Ini bukan satu kesilapan. Ia adalah satu pilihan.
Go tidak menggunakan medan versi untuk modul anda sendiri. Sebaliknya, Go menggunakan git tags.
Untuk menetapkan versi dalam Go, anda lakukan ini:
- git tag v1.2.3
- git push origin v1.2.3
Git tag adalah satu-satunya sumber kebenaran (single source of truth). Apabila seseorang menjalankan go get, Go akan melihat tag repositori anda untuk mencari commit yang betul.
Reka bentuk ini mempunyai kekuatan utama. Versi tidak akan pernah merujuk kepada kod yang salah. Dalam npm, kod yang diterbitkan dan sumber yang ditag boleh terpisah. Dalam Go, kedua-duanya adalah perkara yang sama kerana versi adalah penunjuk (pointer) kepada commit.
Walau bagaimanapun, ini mengubah aliran kerja anda dalam beberapa cara:
- Mencari versi anda memerlukan satu arahan. Anda mesti menjalankan
git describe --tagsdan bukannya melihat fail. - Peningkatan versi (version bumps) tidak muncul dalam semakan kod (code reviews). Tolakan tag (tag push) bukanlah perubahan kod, jadi ia tidak muncul dalam pull request.
- Binaan tempatan (local builds) menggunakan pseudo-versions. Sehingga anda menag commit, anda akan melihat rentetan panjang nombor dan hash dan bukannya versi yang bersih seperti v1.2.3.
- Versi utama (major versions) mengubah laluan import anda. Dalam npm, anda mengubah nombor versi tetapi mengekalkan nama pakej. Dalam Go, v2 dan ke atas memerlukan perubahan laluan seperti /v2. Ini membolehkan sesebuah program menggunakan v1 dan v2 bagi perpustakaan yang sama pada masa yang sama tanpa konflik.
Kebanyakan ekosistem lain menyimpan versi dalam fail:
- Node: package.json
- Rust: Cargo.toml
- Python: pyproject.toml
- Java: pom.xml
- .NET: .csproj
Go adalah berbeza. Ia hanya bergantung pada git tags.
Jika anda mahu binari Go anda memaparkan versi yang bersih, anda boleh menyuntiknya semasa proses binaan menggunakan ldflags. Ramai pembangun juga menggunakan alatan seperti goreleaser untuk mengautomasikan proses tag dan pelepasan (release).
Kedua-dua model ini mewakili keutamaan yang berbeza:
- Versi berasaskan fail mudah dibaca dan disemak. Risikonya ialah fail tersebut boleh terpisah daripada kod sebenar.
- Versi berasaskan tag mustahil untuk dipalsukan. Kosnya ialah ia lebih sukar untuk dilihat dan diurus.
Go memilih model tag untuk memastikan manifes sentiasa sepadan dengan kod.
Bagi mereka yang mengeluarkan kod Go: Bagaimanakah model berasaskan tag sahaja dirasakan dalam kerja harian anda? Adakah anda akan mengubahnya?
Sumber: https://dev.to/dalirnet/packagejson-vs-gomod-where-did-the-version-field-go-3301