
Go Modules là gì?
Go Modules là hệ thống quản lý dependency chính thức của Golang, được giới thiệu từ phiên bản 1.11 và trở thành mặc định từ Go 1.13. Trước khi Go Modules xuất hiện, lập trình viên Golang phải đặt toàn bộ source code vào thư mục GOPATH và dùng công cụ dep hoặc glide quản lý thư viện phụ thuộc — cách làm này lỗi thời và khó bảo trì khi dự án lớn lên. Go Modules giải quyết vấn đề bằng cách cho phép bạn đặt dự án ở bất kỳ đâu trên hệ thống, không còn phụ thuộc vào GOPATH nữa.
Mỗi dự án Golang sử dụng Go Modules sẽ có một file go.mod ở thư mục gốc, file này liệt kê tất cả các module mà dự án phụ thuộc kèm version cụ thể. Khi bạn chạy lệnh go build hoặc go run, Go sẽ tự động tải các module còn thiếu về thư mục go/pkg/mod. Cách này đảm bảo mọi máy trong team đều dùng cùng một version dependency, loại bỏ tình trạng “chạy được ở máy tôi mà không chạy được ở máy bạn”. Điều này đặc biệt quan trọng khi nhiều lập trình viên cùng phát triển một dự án với hàng trăm thư viện phụ thuộc.

Cách khởi tạo và sử dụng Go Modules
Khởi tạo Go Modules cho dự án mới cực kỳ đơn giản. Bạn chỉ cần chạy lệnh go mod init tên-module trong thư mục gốc dự án. Tên module thường có dạng đường dẫn import, ví dụ github.com/username/project. Lệnh này sẽ tạo ra file go.mod với nội dung ban đầu ghi nhận module name và phiên bản Go đang dùng. Sau khi khởi tạo, bạn chỉ việc thêm import các package cần dùng và chạy build, Go sẽ tự động giải quyết phần còn lại.
Khi bạn import một package bên ngoại và chạy go build, Go sẽ tự động thêm dependency đó vào file go.mod. Nếu cần cập nhật tất cả dependency lên phiên bản mới nhất, dùng go get -u ./.... Lệnh go mod tidy sẽ dọn dẹp các dependency không còn dùng và đảm bảo go.mod khớp với code thực tế. Bạn cũng có thể kiểm tra toàn bộ dependency bằng go list -m all hoặc go mod graph để xem cây phụ thuộc đầy đủ.

Quản lý version và semantic versioning
Go Modules tuân theo chuẩn Semantic Versioning (SemVer) với cấu trúc vMAJOR.MINOR.PATCH. Module có thể đóng version bằng tag Git theo đúng chuẩn này, ví dụ v1.2.3. Khi bạn chạy go get, Go sẽ chọn version cao nhất nhỏ hơn v2 nếu dự án chưa có version v2 trở lên — đây là hành vi mặc định giúp tránh breaking change đột ngột. Mỗi lần bạn chạy go get, Go sẽ cập nhật cả go.mod và go.sum với các bản ghi checksum mới.
Nếu muốn sử dụng version cụ thể, bạn chỉ cần thêm tag vào lệnh go get github.com/gin-gonic/[email protected]. Go Modules cũng hỗ trợ go.mod với directive replace, cho phép bạn thay thế một module bằng module khác — cực kỳ hữu ích khi bạn đang phát triển hai module liên quan với nhau và muốn test local trước khi publish. Ví dụ: replace github.com/old/module => ../new-module. Lưu ý rằng replace chỉ hoạt động trong local, không được publish lên remote.
Go Module Proxy: kiến trúc và bảo mật
Bắt đầu từ Go 1.13, Go sử dụng module proxy mặc định là proxy.golang.org. Khi bạn yêu cầu một module, Go sẽ tải từ proxy này thay vì trực tiếp từ repository gốc. Proxy giúp tăng tốc độ tải module, đảm bảo module không bị xóa hoặc thay đổi sau khi đã được publish — module đã public sẽ được lưu trữ vĩnh viễn và không thể thay đổi nội dung. Điều này ngăn chặn supply chain attack dạng “left-pad” hoặc tương tự.

Bạn cũng có thể tự host module proxy nội bộ cho công ty bằng công cụ athens hoặc Gitea với proxy tích hợp. Đối với module private, đặt GOPRIVATE=github.com/company/* để bỏ qua proxy công cộng và truy cập trực tiếp từ nguồn nội bộ. SumDB (sum.golang.org) là cơ sở dữ liệu checksum công khai, đảm bảo module bạn tải về không bị thay đổi bởi kẻ tấn công. Nếu checksum của module download không khớp với SumDB, Go sẽ từ chối build với thông báo lỗi rõ ràng.
Một số lưu ý quan trọng khi làm việc với Go Modules: luôn giữ go.mod và go.sum ở trạng thái cập nhật bằng go mod tidy trước khi commit. File go.sum chứa cryptographic hash của từng module — đây là cơ chế bảo vệ chống lại dependency confusion và supply chain attack. Nếu hash không khớp, Go sẽ từ chối build. Đối với module private (nội bộ công ty), bạn có thể cấu hình GOPRIVATE để bỏ qua proxy và truy cập trực tiếp từ nguồn.
Những sai lầm thường gặp và cách tránh
Một số sai lầm phổ biến khi dùng Go Modules bao gồm: commit file go.sum rỗng (gây lỗi build CI/CD), đặt version v0.0.0 (không ổn định), hoặc dùng latest thay vì version cụ thể. Luôn dùng go mod tidy trước khi commit để đảm bảo file dependency là sạch và đầy đủ. Nên dùng go mod vendor nếu muốn nhúng dependency vào local, giúp build offline và tránh thay đổi từ xa. Cuối cùng, đừng quên cấu hình GO111MODULE=on nếu dự án cũ chưa có file go.mod, hoặc nâu cấp Go lên phiên bản mới nhất để hưởng đủ tính năng bảo mật.
