package.json so với go.mod: Trường phiên bản đã đi đâu mất rồi?
Nếu bạn chuyển từ JavaScript sang Go, có một điều sẽ khiến bạn ngạc nhiên.
Mở một tệp package.json. Bạn sẽ thấy một trường version ngay trên cùng. Nó rất dễ đọc. Bạn có thể thay đổi nó trong một pull request. Nó nằm ngay bên trong mã nguồn của bạn.
Bây giờ, hãy mở một tệp go.mod.
Trường phiên bản không hề có ở đó. Đây không phải là một sai sót. Đó là một sự lựa chọn.
Go không sử dụng trường phiên bản cho module của chính bạn. Thay vào đó, nó sử dụng git tags.
Cách thức hoạt động:
• Bạn chạy git tag v1.2.3
• Bạn push tag đó lên repository của mình
• Tag đó sẽ trở thành phiên bản của bạn
Khi ai đó chạy go get, Go sẽ kiểm tra các git tags của bạn để tìm đúng commit. Tag chính là nguồn sự thật duy nhất (single source of truth).
Thiết kế này có một ưu điểm lớn. Một phiên bản sẽ không bao giờ trỏ nhầm vào mã nguồn. Trong npm, mã nguồn đã xuất bản và trường phiên bản có thể bị lệch nhau. Trong Go, chúng là một. Phiên bản chính là commit.
Tuy nhiên, điều này làm thay đổi quy trình làm việc của bạn:
- Khả năng hiển thị: Bạn không thể thấy phiên bản của mình chỉ bằng cách nhìn vào một tệp. Bạn phải chạy một lệnh git để tìm nó.
- Code Reviews: Việc tăng phiên bản (version bump) không hiển thị trong code diff. Đó là một thao tác push tag, không phải là một thay đổi mã nguồn.
- Build cục bộ: Một commit không có tag sẽ hiển thị một
pseudo-versionlộn xộn. Bạn chỉ có được một phiên bản sạch sẽ sau khi bạn gắn tag cho commit đó. - Các phiên bản lớn (Major Versions): Đây là thay đổi lớn nhất. Trong Go, từ v2 trở lên phải bao gồm phiên bản trong đường dẫn import.
Ví dụ:
v1 sử dụng github.com/you/my-app
v2 sử dụng github.com/you/my-app/v2
Điều này cho phép một chương trình sử dụng hai phiên bản lớn khác nhau của cùng một thư viện mà không gây xung đột.
Hầu hết các ngôn ngữ khác đều giữ phiên bản trong một tệp:
• Node: package.json
• Rust: Cargo.toml
• Python: pyproject.toml
• Java: pom.xml
Go là một ngoại lệ. Nó phụ thuộc hoàn toàn vào git tags.
Nếu bạn nhớ trải nghiệm của npm, bạn có thể chèn phiên bản vào file binary của mình tại thời điểm build bằng cách sử dụng ldflags. Điều này cho phép ứng dụng của bạn phản hồi lệnh kiểm tra phiên bản.
Sự đánh đổi rất đơn giản: Một trường phiên bản thì dễ đọc và dễ xem xét, nhưng nó có thể không chính xác. Một git tag thì khó thấy, nhưng nó luôn luôn đúng.
Go đã chọn sự thật thay vì sự tiện lợi.
Gửi các nhà phát triển Go: Đây có phải là mô hình tốt nhất không? Bạn có muốn có một trường phiên bản trong go.mod nếu các công cụ có thể xác thực nó với git tag không?
Nguồn: https://dev.to/dalirnet/packagejson-vs-gomod-where-did-the-version-field-go-3301