Quản lí Package Trong GoLang

Bài viết được sự cho phép của tác giả Nguyễn Hữu Đồng

Khi làm việc với một ngôn ngữ, do giới hạn của các thư viện có sẵn, chúng ta chắc hẳn đều viết ra một thư viện riêng hoặc ít nhất là dùng thư viện của người khác viết.

Do mỗi người đều có một phong cách viết hay cách tiếp cận khác nhau nên sinh ra chuyện rất khó để mọi người có thể dùng các thư viện của nhau, và thậm chí trong mỗi phiên bản của một cá nhân đều có như thay đổi khiến cho việc sử dụng của người khác bị ảnh hưởng.

  Channel trong Golang là gì? So sánh Callback function và mutex lock với channel

  Chiến trường sinh tử phiên bản lập trình : Python vs Ruby vs Golang

Và để giải quyết vấn đề này, cộng đồng sẽ quy định ra một tiêu chuẩn chung cho một thư viện được viết ra tuân thủ theo trình quản lí thư viện của cộng đồng đó, vị dụ bạn viết Nodejs Package thì bạn phải tuân thủ theo nguyên tắc của npm, hay nếu bạn viết một thư viện trong golang thì bạn phải tuân thủ theo tiêu chuẩn của go module.

Ví dụ, là tiêu chuẩn về phiên bản, mỗi phiên bản thường có dạng [email protected] trong đó x là phiên bản chính, y là phiên bản phụ và z là phiên bản bản vá, đơn cử nếu có 3 phiên bản là 1.1.3, 1.1.9, và 2.0.0 hai phiên bản đầu dường như không có gì khác nhau chỉ có điều khác là phiên bản 1.1.9 được release cùng những bản vá lỗi của 1.1.3 , còn 2.0.0 thì đây là một phiên bản hoàn toàn mới so với 1.1.3

Trong GoLang có hai khái niệm liên quan đến quản lí gói là Go Package và Go Module. Mỗi Go Package là tập hợp các file trong cùng một thư mục, hướng tới xử lí một tập hợp các vấn đề có liên quan đến thứ mà Package đó hướng tới, ví dụ, trong thư mục user của mình mình có 3 file .go cùng xử lí các vấn đề liên quan đối với user thì mình sẽ đặt tên package là user, việc này giúp năng cao khả năng tái sử dụng code cho những project sau này. Còn Go Module là tập hợp của các Go Package, mỗi project là một module và các package được sử dụng trong module đều được go quản lí bằng go.mod file.

Để tạo một module chạy lệnh. Và go.mod sẽ được tạo ra.

go mod init <module name>.
ví dụ : go mod init github.com/dongnguyenltqb/go-simple
        go mod init go-simple
Image for post

Trong mỗi file go.mod thì có ba phần chính. Phần đâu khai báo tên module, thông thường tên module giống với một url chỉ tới git responstory của module đó và phiên bản go đang sử dụng. Phần thứ 2 là phần tuỳ chỉnh URL của package, đa số là rút gọn , mỗi khi bạn import một package thay vì phải viết dài như “import “github.com/dongnguyenltqb/demo/untils” giờ nếu bạn thay thế phần “github.com/dongnguyenltqb/demo” bằng “demo/utils” thì sẽ đỡ tốn công . Thực hiện bằng cách thêm dòng chữ sau vào, phần thứ 2 trên “require”. Và khi build go sẽ get các package đó bằng url gốc.

replace demo=> github.com/dongnguyenltqb/demo

Phần thứ 3 đây là phân quan trọng nhất, chỉ định rõ những Package mà bạn dùng trong module, bao gồm phiên bản, chú thích // indirect chỉ ra rằng module của bạn không dùng trực tiếp Package này mà một trong số những package bạn đang sử dụng dùng package đó, chú thích +incompatible chỉ ra việc Go đã bỏ qua những quy định về quản lí phiên bản theo tiêu chuẩn Semver

Thông thường khi cài đặt một package bằng cách sử dụng “go get” thì mặc định go sẽ tải xuống phiên bản mới nhất của package, để tránh điều này bạn có thể chỉ định rõ version, thậm chí là cả commit và branch của package.

$ go get <path-to-repo>@<branch>
$ go get <path-to-repo>@<commit>
$ go get <path-to-repo>@<version>

Ngoài go.mod còn có thêm go.sum, file này giúp go xác định chính xác version bạn đang sử dụng bằng mã checksum với những version khác đã được cache qua các lần go get trước. Nếu có nhiều người cùng làm việc chung một project, khi họ clone code về nếu trong project có tồn tại file go.sum thì khi download các dependency package, sẽ có những cảnh báo được đưa ra nếu checksum của phiên bản khác với, checksum trong go.sum file, điều này gíup ta cẩn trọng hơn với những gì được đưa vào project.

Và Module trong go có thể là Private, điều này dễ đến go không thể checksum cho package đó, nhưng điều này hoàn toàn có thể bypass dễ bằng bằng cách bỏ qua việc checksum nó, Go cung cấp ba cách để thực hiện, một là khai bao danh sách Private repository hai là thêm responstory vào danh sách bỏ qua checksum hoặc tắt hẳn luôn việc checksum 😀

Để khai báo danh sách các Private repository, set lại giá trị của GOPRIVATE, GOPRIVATE là một biến môt trường của go, thay vì set bằng tay kiểu

go env -w KEY=VALUE

thì bạn có thể Edit thẳng và tự động edit mỗi lần khi mở Terminal bằng cách chỉnh sửa file ~/.bash_profile như hình dưới

sudo vi ~/.bash_profile
Image for post

Cách hai là khai báo danh sách cách responstorykhông cần thực hiện checksum cũng tương tự cách trên chỉ khác tên biến môi trường là GONOSUMDB

export GONOSUMDB="gitlab.com/dongnguyenltqb"

Lưu ý bạn không cần chỉ định rõ hoàn toàn url của responstory, nếu set “gitlab.com/dongnguyenltqb” thì mặc đinhj nõ sẽ có hiệu lực “gitlab.com/dongnguyenltqb/go-demo” hay “gitlab.com/dongnguyenltqb/go-medo”.

Hoặc cách củ chuối hơn là tắt luôn Go Check Sum bằng cách set biến GOSUMDB = off

go env -w GOSUMDB=off

Và sau này, nếu chúng ta hoặc các package không dùng package phụ nào nữa thì ta có thể nhờ Go check và remove các package không cần thiết bằng lệnh.

go mod tidy

Tổng kết, với sự ra đời của Go Module, chúng ta sẽ ko cần phải đặt tất cả các project vào trong Go Path, ta có thể copy project ra nhiều nơi và có thể tự do edit code mà không ảnh hưởng đến project còn lại. Việc này giúp ta quản lí được linh động hơn.

Đến đây là hết rồi, cảm ơn các bạn đã đọc bài. 😀 Nếu có gì sai mong các bạn comment để mình xem lại và sửa chữa. Bye bye các bạn ^_^

Bài viết gốc được đăng tải tại dongnguyenltqb.medium.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev