Tham chiếu về Go Modules
Giới thiệu
Module là cách Go quản lý các dependency.
Tài liệu này là sổ tay tham khảo chi tiết về hệ thống module của Go. Để giới thiệu về việc tạo các dự án Go, xem Cách viết mã Go. Để biết thông tin về việc sử dụng module, chuyển đổi dự án sang module và các chủ đề khác, xem chuỗi bài viết trên blog bắt đầu với Sử dụng Go Modules.
Module, gói và phiên bản
Một module là tập hợp các gói được phát hành, quản lý phiên bản và phân phối cùng nhau. Module có thể được tải xuống trực tiếp từ các kho lưu trữ quản lý phiên bản hoặc từ các máy chủ proxy module.
Một module được xác định bằng đường dẫn module, được khai báo trong tệp go.mod, cùng với thông tin về các dependency của module. Thư mục gốc của module là thư mục chứa tệp go.mod. Module chính là module chứa thư mục nơi lệnh go được gọi.
Mỗi gói trong một module là tập hợp các tệp mã nguồn trong cùng một thư mục được biên dịch cùng nhau. Đường dẫn gói là đường dẫn module được nối với thư mục con chứa gói đó (tính tương đối với thư mục gốc của module). Ví dụ, module "golang.org/x/net" chứa một gói trong thư mục "html". Đường dẫn của gói đó là "golang.org/x/net/html".
Đường dẫn module
Đường dẫn module là tên chính thức của một module, được khai báo bằng chỉ thị module trong tệp go.mod của module. Đường dẫn của module là tiền tố cho các đường dẫn gói trong module.
Đường dẫn module nên mô tả cả chức năng của module và nơi tìm thấy nó. Thông thường, đường dẫn module bao gồm đường dẫn gốc của kho lưu trữ, một thư mục trong kho lưu trữ (thường là rỗng) và hậu tố phiên bản chính (chỉ dành cho phiên bản chính 2 trở lên).
- Đường dẫn gốc của kho lưu trữ là phần của đường dẫn module tương ứng với thư mục gốc của kho lưu trữ quản lý phiên bản nơi module được phát triển. Hầu hết module được định nghĩa trong thư mục gốc của kho lưu trữ, vì vậy đây thường là toàn bộ đường dẫn. Ví dụ,
golang.org/x/netlà đường dẫn gốc của kho lưu trữ cho module cùng tên. Xem Tìm kho lưu trữ cho đường dẫn module để biết thông tin về cách lệnhgođịnh vị kho lưu trữ bằng các yêu cầu HTTP được tạo từ đường dẫn module. - Nếu module không được định nghĩa trong thư mục gốc của kho lưu trữ, thư mục con của module là phần của đường dẫn module đặt tên cho thư mục đó, không bao gồm hậu tố phiên bản chính. Phần này cũng đóng vai trò là tiền tố cho các thẻ phiên bản ngữ nghĩa. Ví dụ, module
golang.org/x/tools/goplsnằm trong thư mục congoplscủa kho lưu trữ có đường dẫn gốcgolang.org/x/tools, vì vậy nó có thư mục con module làgopls. Xem Ánh xạ phiên bản thành commit và Các thư mục module trong một kho lưu trữ. - Nếu module được phát hành ở phiên bản chính 2 trở lên, đường dẫn module phải kết thúc bằng hậu tố phiên bản chính như
/v2. Hậu tố này có thể có hoặc không là một phần của tên thư mục con. Ví dụ, module có đường dẫngolang.org/x/repo/sub/v2có thể nằm trong thư mục con/subhoặc/sub/v2của kho lưu trữgolang.org/x/repo.
Nếu một module có thể được các module khác sử dụng làm dependency, các quy tắc này phải được tuân theo để lệnh go có thể tìm và tải xuống module. Ngoài ra còn có một số hạn chế về cú pháp đối với các ký tự được phép trong đường dẫn module.
Một module sẽ không bao giờ được tải xuống làm dependency của bất kỳ module nào khác có thể sử dụng bất kỳ đường dẫn gói hợp lệ nào cho đường dẫn module của nó, nhưng phải cẩn thận để không xung đột với các đường dẫn có thể được dependency của module hoặc thư viện chuẩn Go sử dụng. Thư viện chuẩn Go sử dụng các đường dẫn gói không chứa dấu chấm trong phần tử đường dẫn đầu tiên, và lệnh go không cố gắng phân giải các đường dẫn như vậy từ các máy chủ mạng. Các đường dẫn example và test được dành riêng cho người dùng: chúng sẽ không được sử dụng trong thư viện chuẩn và phù hợp để dùng trong các module độc lập, chẳng hạn như các module được định nghĩa trong hướng dẫn hoặc mã ví dụ, hoặc được tạo và thao tác như một phần của bài kiểm thử.
Các phiên bản
Một phiên bản xác định một ảnh chụp bất biến của một mô-đun, có thể là một bản phát hành hoặc một pre-release. Mỗi phiên bản bắt đầu bằng chữ cái v, theo sau là một phiên bản semantic. Xem Semantic Versioning 2.0.0 để biết chi tiết về cách các phiên bản được định dạng, diễn giải và so sánh.
Tóm lại, một phiên bản semantic bao gồm ba số nguyên không âm (các phiên bản major, minor và patch, từ trái sang phải) được phân cách bằng dấu chấm. Phiên bản patch có thể được theo sau bởi một chuỗi pre-release tùy chọn bắt đầu bằng dấu gạch nối. Chuỗi pre-release hoặc phiên bản patch có thể được theo sau bởi một chuỗi metadata bản dựng bắt đầu bằng dấu cộng. Ví dụ, v0.0.0, v1.12.134, v8.0.5-pre và v2.0.9+meta là các phiên bản hợp lệ.
Mỗi phần của một phiên bản cho biết phiên bản đó có ổn định hay không và có tương thích với các phiên bản trước hay không.
- Phiên bản major phải được tăng lên và các phiên bản minor cùng patch phải được đặt thành 0 sau khi có thay đổi không tương thích ngược đối với interface công khai của mô-đun hoặc chức năng được ghi chép, ví dụ như sau khi một gói bị xóa.
- Phiên bản minor phải được tăng lên và phiên bản patch phải được đặt thành 0 sau một thay đổi tương thích ngược, ví dụ như sau khi thêm một hàm mới.
- Phiên bản patch phải được tăng lên sau một thay đổi không ảnh hưởng đến interface công khai của mô-đun, chẳng hạn như sửa lỗi hoặc tối ưu hóa.
- Hậu tố pre-release cho biết một phiên bản là một pre-release. Các phiên bản pre-release được sắp xếp trước các phiên bản phát hành tương ứng. Ví dụ,
v1.2.3-pređứng trướcv1.2.3. - Hậu tố metadata bản dựng bị bỏ qua khi so sánh các phiên bản. Lệnh go chấp nhận các phiên bản có metadata bản dựng và chuyển đổi chúng thành các pseudo-version để duy trì thứ tự tổng thể giữa các phiên bản.
- Hậu tố đặc biệt
+incompatiblebiểu thị một phiên bản được phát hành trước khi di chuyển sang mô-đun phiên bản major 2 hoặc mới hơn (xem Compatibility with non-module repositories). - Hậu tố đặc biệt
+dirtyđược thêm vào thông tin phiên bản của một binary khi nó được xây dựng bằng một bộ công cụ Go 1.24 hoặc mới hơn trong một kho lưu trữ Version Control System (VCS) cục bộ hợp lệ có chứa các thay đổi chưa commit trong thư mục làm việc.
- Hậu tố đặc biệt
Một phiên bản được xem là không ổn định nếu phiên bản major của nó là 0 hoặc nó có hậu tố pre-release. Các phiên bản không ổn định không chịu các yêu cầu về tính tương thích. Ví dụ, v0.2.0 có thể không tương thích với v0.1.0, và v1.5.0-beta có thể không tương thích với v1.5.0.
Go có thể truy cập các mô-đun trong hệ thống quản lý phiên bản bằng các tag, nhánh hoặc revision không tuân theo các quy ước này. Tuy nhiên, trong mô-đun chính, lệnh go sẽ tự động chuyển đổi các tên revision không tuân theo tiêu chuẩn này thành các phiên bản chuẩn. Lệnh go cũng sẽ loại bỏ các hậu tố metadata bản dựng (ngoại trừ +incompatible) trong quá trình này. Điều này có thể tạo ra một pseudo-version, một phiên bản pre-release mã hóa một mã định danh revision (chẳng hạn như Git commit hash) và một dấu thời gian từ hệ thống quản lý phiên bản. Ví dụ, lệnh go get golang.org/x/net@daa7c041 sẽ chuyển đổi commit hash daa7c041 thành pseudo-version v0.0.0-20191109021931-daa7c04131f5. Các phiên bản chuẩn là bắt buộc bên ngoài mô-đun chính, và lệnh go sẽ báo lỗi nếu một phiên bản không chuẩn như master xuất hiện trong tệp go.mod.
Pseudo-versions
Một pseudo-version là một version pre-release được định dạng đặc biệt, mã hóa thông tin về một revision cụ thể trong một kho lưu trữ quản lý phiên bản. Ví dụ, v0.0.0-20191109021931-daa7c04131f5 là một pseudo-version.
Pseudo-version có thể tham chiếu đến các revision không có semantic version tags khả dụng. Chúng có thể được dùng để kiểm thử các commit trước khi tạo thẻ version, ví dụ trên một nhánh phát triển.
Mỗi pseudo-version có ba phần:
- Tiền tố version cơ sở (
vX.0.0hoặcvX.Y.Z-0), được suy ra từ một thẻ semantic version đứng trước revision hoặc làvX.0.0nếu không có thẻ như vậy. - Dấu thời gian (
yyyymmddhhmmss), là thời điểm UTC revision được tạo. Trong Git, đây là thời điểm commit, không phải thời điểm của tác giả. - Mã định danh revision (
abcdefabcdef), là tiền tố gồm 12 ký tự của mã băm commit, hoặc trong Subversion là số revision được đệm bằng số 0.
Mỗi pseudo-version có thể có một trong ba dạng, tùy thuộc vào version cơ sở. Các dạng này đảm bảo rằng một pseudo-version được so sánh cao hơn version cơ sở của nó, nhưng thấp hơn version được gắn thẻ tiếp theo.
vX.0.0-yyyymmddhhmmss-abcdefabcdefđược dùng khi không có version cơ sở đã biết. Giống như mọi version khác, version chínhXphải khớp với major version suffix của module.vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdefđược dùng khi version cơ sở là một pre-release version nhưvX.Y.Z-pre.vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdefđược dùng khi version cơ sở là một bản phát hành nhưvX.Y.Z. Ví dụ, nếu version cơ sở làv1.2.3, một pseudo-version có thể làv1.2.4-0.20191109021931-daa7c04131f5.
Nhiều hơn một pseudo-version có thể tham chiếu đến cùng một commit bằng cách sử dụng các version cơ sở khác nhau. Điều này xảy ra tự nhiên khi một version thấp hơn được gắn thẻ sau khi một pseudo-version được tạo.
Các dạng này cung cấp cho pseudo-version hai thuộc tính hữu ích:
- Pseudo-version có version cơ sở đã biết được sắp xếp cao hơn các version đó nhưng thấp hơn các pre-release khác của các version sau.
- Pseudo-version có cùng tiền tố version cơ sở được sắp xếp theo thứ tự thời gian.
Lệnh go thực hiện một số kiểm tra để đảm bảo các tác giả module có quyền kiểm soát cách pseudo-version được so sánh với các version khác và pseudo-version tham chiếu đến các revision thực sự thuộc lịch sử commit của module.
- Nếu một version cơ sở được chỉ định, phải có một thẻ semantic version tương ứng là tổ tiên của revision được mô tả bởi pseudo-version. Điều này ngăn các nhà phát triển vượt qua minimal version selection bằng cách sử dụng một pseudo-version được so sánh cao hơn mọi version đã gắn thẻ như
v1.999.999-99999999999999-daa7c04131f5. - Dấu thời gian phải khớp với dấu thời gian của revision. Điều này ngăn kẻ tấn công làm tràn module proxies bằng một số lượng không giới hạn các pseudo-version vốn giống nhau về mọi mặt khác. Điều này cũng ngăn người dùng module thay đổi thứ tự tương đối của các version.
- Revision phải là tổ tiên của một trong các nhánh hoặc thẻ của kho lưu trữ module. Điều này ngăn kẻ tấn công tham chiếu đến các thay đổi chưa được phê duyệt hoặc các yêu cầu pull.
Không bao giờ cần phải tự nhập pseudo-version bằng tay. Nhiều lệnh chấp nhận mã băm commit hoặc tên nhánh và sẽ tự động chuyển đổi chúng thành pseudo-version (hoặc version đã gắn thẻ nếu có). Ví dụ:
go get example.com/mod@master
go list -m -json example.com/mod@abcd1234
Hậu tố phiên bản chính
Bắt đầu từ phiên bản chính 2, đường dẫn module phải có hậu tố phiên bản
chính như /v2 khớp với phiên bản chính. Ví dụ, nếu một module có đường dẫn
example.com/mod tại v1.0.0, thì module đó phải có đường dẫn
example.com/mod/v2 ở phiên bản v2.0.0.
Các hậu tố phiên bản chính triển khai quy tắc tương thích khi import:
Nếu một gói cũ và một gói mới có cùng đường dẫn import, gói mới phải tương thích ngược với gói cũ.
Theo định nghĩa, các gói trong một phiên bản chính mới của module không tương thích
ngược với các gói tương ứng trong phiên bản chính trước đó. Do đó, bắt đầu từ
v2, các gói cần có đường dẫn import mới. Điều này được thực hiện bằng cách thêm
hậu tố phiên bản chính vào đường dẫn module. Vì đường dẫn module là tiền tố của
đường dẫn import cho mỗi gói bên trong module, việc thêm hậu tố phiên bản chính
vào đường dẫn module cung cấp một đường dẫn import riêng biệt cho mỗi phiên bản
không tương thích.
Hậu tố phiên bản chính không được phép ở các phiên bản chính v0 hoặc v1. Không
cần thay đổi đường dẫn module giữa v0 và v1 vì các phiên bản v0 không ổn định
và không có đảm bảo về tính tương thích. Ngoài ra, với hầu hết các module, v1
tương thích ngược với phiên bản v0 cuối cùng; một phiên bản v1 thể hiện cam
kết về tính tương thích, thay vì chỉ ra các thay đổi không tương thích so với
v0.
Một trường hợp đặc biệt là các đường dẫn module bắt đầu bằng gopkg.in/ phải
luôn có hậu tố phiên bản chính, ngay cả ở v0 và v1. Hậu tố phải bắt đầu bằng
dấu chấm thay vì dấu gạch chéo (ví dụ, gopkg.in/yaml.v2).
Các hậu tố phiên bản chính cho phép nhiều phiên bản chính của một module cùng tồn tại trong một bản build. Điều này có thể cần thiết do vấn đề dependency hình kim cương. Thông thường, nếu một module được yêu cầu ở hai phiên bản khác nhau bởi các dependency bắc cầu, phiên bản cao hơn sẽ được sử dụng. Tuy nhiên, nếu hai phiên bản không tương thích, không phiên bản nào có thể đáp ứng tất cả client. Vì các phiên bản không tương thích phải có số phiên bản chính khác nhau, chúng cũng phải có đường dẫn module khác nhau do hậu tố phiên bản chính. Điều này giải quyết xung đột: các module có hậu tố khác nhau được xem là các module riêng biệt, và các gói của chúng—ngay cả các gói trong cùng thư mục con tính tương đối so với gốc module— đều là các gói khác nhau.
Nhiều dự án Go đã phát hành các phiên bản v2 hoặc cao hơn mà không sử dụng hậu
tố phiên bản chính trước khi chuyển sang module (có thể là trước cả khi module
được giới thiệu). Các phiên bản này được đánh dấu bằng build tag
+incompatible (ví dụ, v2.0.0+incompatible). Xem Tính tương thích với các
repository không phải module để biết thêm thông tin.
Xác định một gói thành một module
Khi lệnh go tải một gói bằng cách sử dụng đường dẫn
gói, nó cần xác định module nào cung cấp gói đó.
Lệnh go bắt đầu bằng cách tìm kiếm danh sách build để
tìm các module có đường dẫn là tiền tố của đường dẫn gói. Ví dụ, nếu gói
example.com/a/b được nhập, và module example.com/a có trong danh sách
build, lệnh go sẽ kiểm tra xem example.com/a có chứa gói đó hay không,
trong thư mục b. Một thư mục phải có ít nhất một tệp có phần mở rộng .go
để được xem là một gói. Các ràng buộc
build không được áp dụng cho mục đích
này. Nếu chính xác một module trong danh sách build cung cấp gói đó, module đó
sẽ được sử dụng. Nếu không có module nào cung cấp gói hoặc có hai hay nhiều
module cung cấp gói, lệnh go sẽ báo lỗi. Cờ -mod=mod chỉ dẫn lệnh go cố
gắng tìm các module mới cung cấp các gói bị thiếu và cập nhật go.mod cùng
go.sum. Các lệnh go get và go mod tidy thực
hiện việc này tự động.
Khi lệnh go tra cứu một module mới cho đường dẫn gói, nó kiểm tra biến môi
trường GOPROXY, đây là danh sách các URL proxy được phân tách bằng dấu phẩy
hoặc các từ khóa direct hay off. Một URL proxy cho biết lệnh go nên liên
hệ với một module proxy bằng cách sử dụng giao thức
GOPROXY. direct cho biết lệnh go nên
liên lạc với một hệ thống quản lý phiên bản. off cho biết không nên
thực hiện liên lạc nào. Các biến môi trường
GOPRIVATE và GONOPROXY cũng có thể được sử dụng để kiểm soát hành vi này.
Đối với mỗi mục trong danh sách GOPROXY, lệnh go yêu cầu phiên bản mới nhất
của từng đường dẫn module có thể cung cấp gói (nghĩa là từng tiền tố của đường
dẫn gói). Với mỗi đường dẫn module được yêu cầu thành công, lệnh go sẽ tải
module ở phiên bản mới nhất và kiểm tra xem module có chứa gói được yêu cầu
hay không. Nếu một hoặc nhiều module chứa gói được yêu cầu, module có đường
dẫn dài nhất sẽ được sử dụng. Nếu tìm thấy một hoặc nhiều module nhưng không
module nào chứa gói được yêu cầu, lỗi sẽ được báo cáo. Nếu không tìm thấy
module nào, lệnh go thử mục tiếp theo trong danh sách GOPROXY. Nếu không
còn mục nào, lỗi sẽ được báo cáo.
Ví dụ, giả sử lệnh go đang tìm một module cung cấp gói
golang.org/x/net/html, và GOPROXY được đặt thành
https://corp.example.com,https://proxy.golang.org. Lệnh go có thể thực hiện
các yêu cầu sau:
- Đến
https://corp.example.com/(song song):- Yêu cầu phiên bản mới nhất của
golang.org/x/net/html - Yêu cầu phiên bản mới nhất của
golang.org/x/net - Yêu cầu phiên bản mới nhất của
golang.org/x - Yêu cầu phiên bản mới nhất của
golang.org
- Yêu cầu phiên bản mới nhất của
- Đến
https://proxy.golang.org/, nếu tất cả các yêu cầu đếnhttps://corp.example.com/đã thất bại với 404 hoặc 410:- Yêu cầu phiên bản mới nhất của
golang.org/x/net/html - Yêu cầu phiên bản mới nhất của
golang.org/x/net - Yêu cầu phiên bản mới nhất của
golang.org/x - Yêu cầu phiên bản mới nhất của
golang.org
- Yêu cầu phiên bản mới nhất của
Sau khi tìm thấy một module phù hợp, lệnh go sẽ thêm một
yêu cầu mới với đường dẫn và phiên bản của module mới
vào tệp go.mod của module chính. Điều này đảm bảo rằng khi cùng một gói được
tải trong tương lai, cùng một module sẽ được sử dụng ở cùng một phiên bản. Nếu
gói đã xác định không được nhập bởi một gói trong module chính, yêu cầu mới sẽ
có một chú thích // indirect.
go.mod files
Một module được định nghĩa bằng một tệp văn bản được mã hóa UTF-8 có tên go.mod trong thư mục gốc của nó. Tệp go.mod có cấu trúc theo dòng. Mỗi dòng chứa một chỉ thị duy nhất, bao gồm một từ khóa theo sau bởi các đối số. Ví dụ:
module example.com/my/thing
go 1.23.0
require example.com/other/thing v1.0.2
require example.com/new/thing/v2 v2.3.4
exclude example.com/old/thing v1.2.3
replace example.com/bad/thing v1.4.5 => example.com/good/thing v1.4.5
retract [v1.9.0, v1.9.5]
Từ khóa ở đầu có thể được tách ra khỏi các dòng liền kề để tạo thành một khối, tương tự như các lệnh import trong Go.
require (
example.com/new/thing/v2 v2.3.4
example.com/old/thing v1.2.3
)
Tệp go.mod được thiết kế để con người có thể đọc và máy có thể ghi. Lệnh go cung cấp một số lệnh con thay đổi các tệp go.mod. Ví dụ, go get có thể nâng cấp hoặc hạ cấp các dependency cụ thể. Các lệnh tải đồ thị module sẽ tự động cập nhật go.mod khi cần. go mod edit có thể thực hiện các chỉnh sửa cấp thấp. Gói golang.org/x/mod/modfile có thể được các chương trình Go sử dụng để thực hiện các thay đổi tương tự theo cách lập trình.
Một tệp go.mod là bắt buộc đối với module chính, và đối với bất kỳ module thay thế nào được chỉ định bằng đường dẫn tệp cục bộ. Tuy nhiên, một module không có tệp go.mod rõ ràng vẫn có thể được yêu cầu làm dependency, hoặc được dùng làm module thay thế được chỉ định bằng đường dẫn module và phiên bản; xem Tính tương thích với các repository không phải module.
Các phần tử từ vựng
Khi một tệp go.mod được phân tích cú pháp, nội dung của nó được chia thành một chuỗi token. Có một số loại token: khoảng trắng, chú thích, dấu câu, từ khóa, định danh và chuỗi.
Khoảng trắng bao gồm dấu cách (U+0020), tab (U+0009), ký tự xuống dòng kiểu carriage return (U+000D) và dòng mới (U+000A). Các ký tự khoảng trắng khác dòng mới không có tác dụng nào ngoài việc phân tách các token vốn sẽ được kết hợp nếu không có chúng. Dòng mới là các token có ý nghĩa.
Chú thích bắt đầu bằng // và kéo dài đến cuối dòng. Không cho phép chú thích dạng /* */.
Token dấu câu bao gồm (, ), và =>.
Từ khóa phân biệt các loại chỉ thị khác nhau trong tệp go.mod. Các từ khóa được phép là module, go, require, replace, exclude, và retract.
Định danh là các chuỗi ký tự không phải khoảng trắng, chẳng hạn như đường dẫn module hoặc phiên bản ngữ nghĩa.
Chuỗi là các chuỗi ký tự được đặt trong dấu ngoặc. Có hai loại chuỗi: chuỗi được diễn giải bắt đầu và kết thúc bằng dấu ngoặc kép (", U+0022) và chuỗi thô bắt đầu và kết thúc bằng dấu huyền (<code>`</code>, U+0060). Chuỗi được diễn giải có thể chứa các chuỗi thoát bao gồm dấu gạch chéo ngược (\, U+005C) theo sau bởi một ký tự khác. Dấu ngoặc kép được thoát (\") không kết thúc một chuỗi được diễn giải. Giá trị không có dấu ngoặc của một chuỗi được diễn giải là chuỗi ký tự nằm giữa các dấu ngoặc kép với mỗi chuỗi thoát được thay thế bằng ký tự đứng sau dấu gạch chéo ngược (ví dụ, \" được thay thế bằng ", \n được thay thế bằng n). Ngược lại, giá trị không có dấu ngoặc của một chuỗi thô chỉ đơn giản là chuỗi ký tự nằm giữa các dấu huyền; dấu gạch chéo ngược không có ý nghĩa đặc biệt trong chuỗi thô.
Định danh và chuỗi có thể thay thế lẫn nhau trong ngữ pháp go.mod.
Đường dẫn module và phiên bản
Hầu hết các định danh và chuỗi trong tệp go.mod là đường dẫn module hoặc phiên bản.
Đường dẫn module phải đáp ứng các yêu cầu sau:
- Đường dẫn phải bao gồm một hoặc nhiều phần tử đường dẫn được phân tách bằng dấu gạch chéo (
/, U+002F). Đường dẫn không được bắt đầu hoặc kết thúc bằng dấu gạch chéo. - Mỗi phần tử đường dẫn là một chuỗi không rỗng được tạo thành từ các chữ cái ASCII, chữ số ASCII và một số dấu câu ASCII giới hạn (
-,.,_và~). - Một phần tử đường dẫn không được bắt đầu hoặc kết thúc bằng dấu chấm (
., U+002E). - Tiền tố của phần tử tính đến dấu chấm đầu tiên không được là tên tệp dành riêng trên Windows, không phân biệt chữ hoa chữ thường (
CON,com1,NuL, v.v.). - Tiền tố của phần tử tính đến dấu chấm đầu tiên không được kết thúc bằng dấu ngã theo sau bởi một hoặc nhiều chữ số (như
EXAMPL~1.COM).
Nếu đường dẫn module xuất hiện trong chỉ thị require và không được thay thế, hoặc nếu đường dẫn module xuất hiện ở phía bên phải của chỉ thị replace, lệnh go có thể cần tải xuống các module có đường dẫn đó, và một số yêu cầu bổ sung phải được đáp ứng.
- Phần tử đường dẫn đứng đầu (đến dấu gạch chéo đầu tiên, nếu có), theo quy ước là tên miền, chỉ được chứa các chữ cái ASCII viết thường, chữ số ASCII, dấu chấm (
., U+002E) và dấu gạch ngang (-, U+002D); nó phải chứa ít nhất một dấu chấm và không được bắt đầu bằng dấu gạch ngang. - Đối với phần tử đường dẫn cuối cùng có dạng
/vNtrong đóNcó dạng số (các chữ số ASCII và dấu chấm),Nkhông được bắt đầu bằng số 0 ở đầu, không được là/v1và không được chứa bất kỳ dấu chấm nào.- Đối với các đường dẫn bắt đầu bằng
gopkg.in/, yêu cầu này được thay thế bằng yêu cầu đường dẫn phải tuân theo các quy ước của dịch vụ gopkg.in.
- Đối với các đường dẫn bắt đầu bằng
Các phiên bản trong tệp go.mod có thể là chuẩn hoặc không chuẩn.
Một phiên bản chuẩn bắt đầu bằng chữ cái v, theo sau là một phiên bản semantic tuân theo đặc tả Semantic Versioning 2.0.0. Xem Versions để biết thêm thông tin.
Hầu hết các định danh và chuỗi khác có thể được dùng làm phiên bản không chuẩn, mặc dù có một số hạn chế để tránh các vấn đề với hệ thống tệp, repository và module proxies. Các phiên bản không chuẩn chỉ được phép trong tệp go.mod của module chính. Lệnh go sẽ cố gắng thay thế mỗi phiên bản không chuẩn bằng một phiên bản chuẩn tương đương khi tự động cập nhật tệp go.mod.
Ở những nơi đường dẫn module được liên kết với một phiên bản (như trong các chỉ thị require, replace và exclude), phần tử đường dẫn cuối cùng phải nhất quán với phiên bản. Xem hậu tố phiên bản chính.
Ngữ pháp
Cú pháp go.mod được chỉ định bên dưới bằng Biểu mẫu Backus-Naur mở rộng (EBNF).
Xem phần Ký hiệu trong Đặc tả Ngôn ngữ Go
để biết chi tiết về cú pháp EBNF.
GoMod = { Directive } .
Directive = ModuleDirective |
GoDirective |
ToolDirective |
IgnoreDirective |
RequireDirective |
ExcludeDirective |
ReplaceDirective |
RetractDirective .
Các dòng mới, định danh và chuỗi lần lượt được ký hiệu bằng newline, ident và
string.
Đường dẫn module và phiên bản được ký hiệu bằng ModulePath và Version.
ModulePath = ident | string . /* xem các hạn chế ở trên */
Version = ident | string . /* xem các hạn chế ở trên */
Chỉ thị module
Chỉ thị module xác định đường dẫn của module chính. Một
tệp go.mod phải chứa chính xác một chỉ thị module.
ModuleDirective = "module" ( ModulePath | "(" newline ModulePath newline ")" ) newline .
Ví dụ:
module golang.org/x/net
Ngừng hỗ trợ
Một module có thể được đánh dấu là ngừng hỗ trợ trong một khối chú thích chứa
chuỗi Deprecated: (phân biệt chữ hoa chữ thường) ở đầu một đoạn văn. Thông báo
ngừng hỗ trợ bắt đầu sau dấu hai chấm và kéo dài đến hết đoạn văn. Các chú thích
có thể xuất hiện ngay trước chỉ thị module hoặc sau đó trên cùng một dòng.
Ví dụ:
// Deprecated: use example.com/mod/v2 instead.
module example.com/mod
Kể từ Go 1.17, go list -m -u kiểm tra thông tin về tất cả các
module đã ngừng hỗ trợ trong danh sách build. go get
kiểm tra các module đã ngừng hỗ trợ cần thiết để build các gói được đặt tên trên
dòng lệnh.
Khi lệnh go lấy thông tin ngừng hỗ trợ cho một module, nó tải tệp go.mod từ
phiên bản khớp với truy vấn phiên bản @latest mà không xem
xét việc thu hồi hoặc loại trừ.
Lệnh go tải danh sách các phiên bản đã thu hồi từ
cùng tệp go.mod.
Để ngừng hỗ trợ một module, tác giả có thể thêm chú thích // Deprecated: và gắn
thẻ một bản phát hành mới. Tác giả có thể thay đổi hoặc xóa thông báo ngừng hỗ
trợ trong một bản phát hành cao hơn.
Việc ngừng hỗ trợ áp dụng cho tất cả các phiên bản minor của một module. Các
phiên bản major cao hơn v2 được xem là các module riêng biệt cho mục đích này,
vì hậu tố phiên bản major của chúng cung cấp cho
chúng các đường dẫn module khác nhau.
Thông báo ngừng hỗ trợ nhằm thông báo cho người dùng rằng module không còn được
hỗ trợ và cung cấp hướng dẫn di chuyển, ví dụ sang phiên bản major mới nhất.
Các phiên bản minor và patch riêng lẻ không thể được đánh dấu ngừng hỗ trợ;
retract có thể phù hợp hơn cho trường hợp đó.
go directive
Một chỉ thị go cho biết một module được viết với giả định về ngữ nghĩa của một phiên bản Go cụ thể. Phiên bản đó phải là một phiên bản Go hợp lệ, chẳng hạn như 1.14, 1.21rc1 hoặc 1.23.0.
Chỉ thị go đặt phiên bản Go tối thiểu cần thiết để sử dụng module này. Trước Go 1.21, chỉ thị này chỉ mang tính khuyến nghị; hiện nay nó là một yêu cầu bắt buộc: các toolchain Go từ chối sử dụng những module khai báo phiên bản Go mới hơn.
Chỉ thị go là đầu vào để lựa chọn toolchain Go nào sẽ chạy.
Xem “các toolchain Go” để biết chi tiết.
Chỉ thị go ảnh hưởng đến việc sử dụng các tính năng ngôn ngữ mới:
- Đối với các gói trong module, trình biên dịch từ chối sử dụng các tính năng ngôn ngữ được giới thiệu sau phiên bản được chỉ định bởi chỉ thị
go. Ví dụ, nếu một module có chỉ thịgo 1.12, các gói của module đó không được sử dụng các literal số như1_000_000, vốn được giới thiệu trong Go 1.13. - Nếu một phiên bản Go cũ hơn xây dựng một trong các gói của module và gặp lỗi biên dịch, lỗi đó cho biết module được viết cho một phiên bản Go mới hơn. Ví dụ, giả sử một module có
go 1.13và một gói sử dụng literal số1_000_000. Nếu gói đó được xây dựng bằng Go 1.12, trình biên dịch sẽ cho biết mã được viết cho Go 1.13.
Chỉ thị go cũng ảnh hưởng đến hành vi của lệnh go:
- Với
go 1.14trở lên, vendoring tự động có thể được bật. Nếu tệpvendor/modules.txttồn tại và nhất quán vớigo.mod, không cần sử dụng rõ ràng cờ-mod=vendor. - Với
go 1.16trở lên, mẫu góiallchỉ khớp với các gói được nhập gián tiếp bởi các gói và bài kiểm thử trong module chính. Đây là cùng tập hợp các gói được giữ lại bởigo mod vendorkể từ khi module được giới thiệu. Trong các phiên bản thấp hơn,allcũng bao gồm các bài kiểm thử của những gói được nhập bởi các gói trong module chính, các bài kiểm thử của những gói đó, v.v. - Với
go 1.17trở lên:- Tệp
go.modbao gồm một chỉ thịrequirerõ ràng cho mỗi module cung cấp bất kỳ gói nào được nhập gián tiếp bởi một gói hoặc bài kiểm thử trong module chính. (Ởgo 1.16trở xuống, một dependency gián tiếp chỉ được đưa vào nếu lựa chọn phiên bản tối thiểu nếu không sẽ chọn một phiên bản khác.) Thông tin bổ sung này cho phép cắt tỉa đồ thị module và tải module lười. - Vì có thể có nhiều
// indirectdependency hơn đáng kể so với các phiên bảngotrước đó, các dependency gián tiếp được ghi lại trong một khối riêng trong tệpgo.mod. go mod vendorbỏ qua các tệpgo.modvàgo.sumcủa các dependency được vendor. (Điều đó cho phép các lần gọi lệnhgobên trong các thư mục con củavendorxác định module chính chính xác.)go mod vendorghi lại phiên bảngotừ tệpgo.modcủa mỗi dependency vàovendor/modules.txt.
- Tệp
- Với
go 1.21trở lên:- Dòng
gokhai báo phiên bản Go tối thiểu bắt buộc để sử dụng với module này. - Dòng
gophải lớn hơn hoặc bằng dònggocủa tất cả dependency. - Lệnh
gokhông còn cố gắng duy trì khả năng tương thích với phiên bản Go cũ hơn trước đó. - Lệnh
gocẩn thận hơn trong việc giữ checksum của các tệpgo.modtrong tệpgo.sum.
- Dòng
Một tệp go.mod có thể chứa nhiều nhất một chỉ thị go. Hầu hết các lệnh sẽ thêm một chỉ thị go với phiên bản Go hiện tại nếu chưa có.
Nếu thiếu chỉ thị go, go 1.16 được giả định.
GoDirective = "go" GoVersion newline .
GoVersion = string | ident . /* phiên bản bản phát hành hợp lệ; xem ở trên */
Ví dụ:
go 1.23.0
toolchain directive
Chỉ thị toolchain khai báo một Go toolchain được đề xuất để sử dụng với một module.
Phiên bản của Go toolchain được đề xuất không được thấp hơn phiên bản Go bắt buộc
được khai báo trong chỉ thị go.
Chỉ thị toolchain
chỉ có tác dụng khi module là module chính và phiên bản của toolchain mặc định
thấp hơn phiên bản của toolchain được đề xuất.
Để đảm bảo khả năng tái tạo, lệnh go ghi tên toolchain của chính nó trong một dòng toolchain bất cứ khi nào
nó cập nhật phiên bản go trong tệp go.mod (thường là trong quá trình go get).
Để biết chi tiết, xem “Go toolchains”.
ToolchainDirective = "toolchain" ToolchainName newline .
ToolchainName = string | ident . /* tên toolchain hợp lệ; xem “Go toolchains” */
Ví dụ:
toolchain go1.21.0
godebug directive
Chỉ thị godebug khai báo một thiết lập GODEBUG duy nhất
để áp dụng khi module này là module chính.
Có thể có nhiều hơn một dòng như vậy và chúng có thể được gom nhóm.
Sẽ là lỗi nếu module chính đặt tên một khóa GODEBUG không tồn tại.
Hiệu ứng của godebug key=value tương tự như việc mọi gói chính đang được biên dịch
chứa một tệp nguồn liệt kê //go:debug key=value.
GodebugDirective = "godebug" ( GodebugSpec | "(" newline { GodebugSpec } ")" newline ) .
GodebugSpec = GodebugKey "=" GodebugValue newline.
GodebugKey = GodebugChar { GodebugChar }.
GodebugValue = GodebugChar { GodebugChar }.
GodebugChar = any non-space character except , " ` ' (comma and quotes).
Ví dụ:
godebug default=go1.21
godebug (
panicnil=1
asynctimerchan=0
)
require directive
Chỉ thị require khai báo phiên bản tối thiểu bắt buộc của một module
dependency nhất định. Với mỗi phiên bản module được yêu cầu, lệnh go tải
tệp go.mod của phiên bản đó và tích hợp các yêu cầu từ
tệp đó. Sau khi tất cả yêu cầu đã được tải, lệnh go giải quyết chúng
bằng minimal version selection (MVS) để tạo ra
build list.
Lệnh go tự động thêm các chú thích // indirect cho một số
yêu cầu. Chú thích // indirect cho biết rằng không có gói nào từ
module được yêu cầu được bất kỳ gói nào trong module
chính nhập trực tiếp.
Nếu chỉ thị go chỉ định go 1.16 hoặc thấp hơn, lệnh go
thêm một yêu cầu gián tiếp khi phiên bản được chọn của một module
cao hơn phiên bản đã được ngầm định (theo bắc cầu) bởi các dependency khác của
module chính. Điều này có thể xảy ra do một lần nâng cấp rõ ràng (go get -u ./...),
loại bỏ một dependency khác trước đó áp đặt yêu cầu (go mod tidy), hoặc một dependency nhập một gói mà không có yêu cầu tương ứng
trong tệp go.mod của chính nó (chẳng hạn một dependency hoàn toàn không có tệp go.mod).
Tại go 1.17 trở lên, lệnh go thêm một yêu cầu gián tiếp cho mỗi
module cung cấp bất kỳ gói nào được nhập (ngay cả
gián tiếp) bởi một gói hoặc bài kiểm thử trong module chính
hoặc được truyền làm đối số cho go get. Các yêu cầu đầy đủ hơn này
cho phép cắt tỉa đồ thị module và tải module
lười.
RequireDirective = "require" ( RequireSpec | "(" newline { RequireSpec } ")" newline ) .
RequireSpec = ModulePath Version newline .
Ví dụ:
require golang.org/x/net v1.2.3
require (
golang.org/x/crypto v1.4.5 // indirect
golang.org/x/text v1.6.7
)
tool directive
Kể từ Go 1.24, chỉ thị tool thêm một gói làm dependency của module hiện tại. Chỉ thị này cũng
cho phép chạy gói đó bằng go tool khi thư mục làm việc hiện tại nằm
trong module này, hoặc trong một workspace chứa module này.
Nếu gói công cụ không nằm trong module hiện tại, phải có chỉ thị require
chỉ định phiên bản của công cụ cần sử dụng.
Mẫu meta tool phân giải thành danh sách các công cụ được định nghĩa trong
go.mod của module hiện tại, hoặc trong chế độ workspace thành hợp của tất cả công cụ được định nghĩa trong tất cả module trong
workspace.
ToolDirective = "tool" ( ToolSpec | "(" newline { ToolSpec } ")" newline ) .
ToolSpec = ModulePath newline .
Ví dụ:
tool golang.org/x/tools/cmd/stringer
tool (
example.com/module/cmd/a
example.com/module/cmd/b
)
ignore directive
Chỉ thị ignore khiến lệnh go bỏ qua các đường dẫn thư mục được phân tách bằng dấu gạch chéo
và mọi tệp hoặc thư mục được chứa đệ quy trong chúng,
khi khớp các mẫu gói.
Nếu đường dẫn bắt đầu bằng ./, đường dẫn được hiểu là tương đối so với
thư mục gốc của module, và thư mục đó cùng mọi thư mục hoặc tệp
được chứa đệ quy trong nó sẽ bị bỏ qua khi khớp các mẫu gói.
Nếu không, mọi thư mục có đường dẫn đó ở bất kỳ độ sâu nào trong module, cùng mọi thư mục hoặc tệp được chứa đệ quy trong chúng sẽ bị bỏ qua.
IgnoreDirective = "ignore" ( IgnoreSpec | "(" newline { IgnoreSpec } ")" newline ) .
IgnoreSpec = RelativeFilePath newline .
RelativeFilePath = /* slash-separated relative file path */ .
Ví dụ
ignore ./node_modules
ignore (
static
content/html
./third_party/javascript
)
exclude directive
Chỉ thị exclude ngăn một phiên bản module được lệnh go
tải.
Kể từ Go 1.16, nếu một phiên bản được tham chiếu bởi chỉ thị require trong bất kỳ tệp go.mod
nào bị loại trừ bởi chỉ thị exclude trong tệp go.mod của module chính,
yêu cầu đó sẽ bị bỏ qua. Điều này có thể khiến các lệnh như go get
và go mod tidy thêm các yêu cầu mới lên các phiên bản cao hơn
vào go.mod, với chú thích // indirect nếu phù hợp.
Trước Go 1.16, nếu một phiên bản bị loại trừ được tham chiếu bởi chỉ thị require,
lệnh go liệt kê các phiên bản khả dụng cho module (như được hiển thị với go list -m -versions) và tải phiên bản không bị loại trừ tiếp theo cao hơn
thay thế. Điều này có thể dẫn đến việc lựa chọn phiên bản không xác định, vì
phiên bản cao hơn tiếp theo có thể thay đổi theo thời gian. Cả phiên bản bản phát hành và pre-release
đều được xem xét cho mục đích này, nhưng pseudo-version thì không. Nếu
không có phiên bản cao hơn, lệnh go báo cáo lỗi.
Các chỉ thị exclude chỉ áp dụng trong tệp go.mod của module chính và bị
bỏ qua trong các module khác. Xem Minimal version
selection để biết chi tiết.
ExcludeDirective = "exclude" ( ExcludeSpec | "(" newline { ExcludeSpec } ")" newline ) .
ExcludeSpec = ModulePath Version newline .
Ví dụ:
exclude golang.org/x/net v1.2.3
exclude (
golang.org/x/crypto v1.4.5
golang.org/x/text v1.6.7
)
replace directive
Chỉ thị replace thay thế nội dung của một phiên bản cụ thể của một module,
hoặc tất cả các phiên bản của một module, bằng nội dung được tìm thấy ở nơi
khác. Phần thay thế có thể được chỉ định bằng một module path và phiên bản khác,
hoặc bằng một đường dẫn tệp dành riêng cho nền tảng.
Nếu có phiên bản ở phía bên trái của mũi tên (=>), chỉ phiên bản cụ thể đó
của module được thay thế; các phiên bản khác sẽ được truy cập bình thường.
Nếu phiên bản bên trái bị bỏ qua, tất cả các phiên bản của module đều được thay
thế.
Nếu path ở phía bên phải của mũi tên là một đường dẫn tuyệt đối hoặc tương đối
(bắt đầu bằng ./ hoặc ../), nó được hiểu là đường dẫn tệp cục bộ đến thư mục
gốc của module thay thế, thư mục này phải chứa tệp go.mod. Trong trường hợp
này, phiên bản thay thế phải được bỏ qua.
Nếu path ở phía bên phải không phải là đường dẫn cục bộ, nó phải là một module path hợp lệ. Trong trường hợp này, phiên bản là bắt buộc. Cùng một phiên bản module không được đồng thời xuất hiện trong danh sách build.
Bất kể việc thay thế được chỉ định bằng đường dẫn cục bộ hay module path, nếu
module thay thế có tệp go.mod, chỉ thị module của nó phải khớp với module
path mà nó thay thế.
Các chỉ thị replace chỉ áp dụng trong tệp go.mod của module chính
và bị bỏ qua trong các module khác. Xem Minimal version
selection để biết chi tiết.
Nếu có nhiều module chính, các tệp go.mod của tất cả module chính đều được áp
dụng. Các chỉ thị replace xung đột giữa các module chính không được phép,
và phải được xóa hoặc ghi đè trong
một replace trong tệp go.work.
Lưu ý rằng chỉ một chỉ thị replace không tự thêm module vào module
graph. Cũng cần có một chỉ thị
require tham chiếu đến phiên bản module đã thay thế,
hoặc trong tệp go.mod của module chính hoặc trong tệp go.mod của một
dependency. Một chỉ thị replace không có tác dụng nếu phiên bản module ở
phía bên trái không được yêu cầu.
ReplaceDirective = "replace" ( ReplaceSpec | "(" newline { ReplaceSpec } ")" newline ) .
ReplaceSpec = ModulePath [ Version ] "=>" FilePath newline
| ModulePath [ Version ] "=>" ModulePath Version newline .
FilePath = /* platform-specific relative or absolute file path */
Ví dụ:
replace golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
replace (
golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
golang.org/x/net => example.com/fork/net v1.4.5
golang.org/x/net v1.2.3 => ./fork/net
golang.org/x/net => ./fork/net
)
retract directive
Một chỉ thị retract cho biết rằng không nên phụ thuộc vào một phiên bản hoặc một dải phiên bản của module được định nghĩa bởi go.mod. Một chỉ thị retract hữu ích khi một phiên bản được xuất bản quá sớm hoặc một vấn đề nghiêm trọng được phát hiện sau khi phiên bản đó được xuất bản. Các phiên bản bị thu hồi vẫn nên có sẵn trong các repository quản lý phiên bản và trên module
proxies để đảm bảo rằng các bản dựng phụ thuộc vào chúng không bị hỏng. Từ retract được mượn từ tài liệu học thuật: một bài nghiên cứu bị thu hồi vẫn có sẵn, nhưng nó có vấn đề và không nên là cơ sở cho công việc trong tương lai.
Khi một phiên bản module bị thu hồi, người dùng sẽ không tự động nâng cấp lên phiên bản đó bằng cách sử dụng go get, go mod tidy, hoặc các lệnh khác. Các bản dựng phụ thuộc vào những phiên bản bị thu hồi vẫn nên tiếp tục hoạt động, nhưng người dùng sẽ được thông báo về việc thu hồi khi họ kiểm tra bản cập nhật bằng go list -m -u hoặc cập nhật một module liên quan bằng go get.
Để thu hồi một phiên bản, tác giả module nên thêm một chỉ thị retract vào go.mod, sau đó xuất bản một phiên bản mới chứa chỉ thị đó. Phiên bản mới phải cao hơn các phiên bản bản phát hành hoặc pre-release khác; nghĩa là truy vấn phiên bản @latest version query phải phân giải thành phiên bản mới trước khi xem xét các lần thu hồi. Lệnh go tải và áp dụng các lần thu hồi từ phiên bản được hiển thị bởi go list -m -retracted $modpath@latest (trong đó $modpath là đường dẫn module).
Các phiên bản bị thu hồi được ẩn khỏi danh sách phiên bản được in bởi go list -m -versions trừ khi sử dụng cờ -retracted. Các phiên bản bị thu hồi bị loại trừ khi phân giải các truy vấn phiên bản như @>=v1.2.3 hoặc @latest.
Một phiên bản chứa các lần thu hồi có thể tự thu hồi chính nó. Nếu phiên bản bản phát hành hoặc pre-release cao nhất của một module tự thu hồi chính nó, truy vấn @latest sẽ phân giải thành một phiên bản thấp hơn sau khi loại trừ các phiên bản bị thu hồi.
Ví dụ, hãy xem xét trường hợp tác giả của module example.com/m vô tình xuất bản phiên bản v1.0.0. Để ngăn người dùng nâng cấp lên v1.0.0, tác giả có thể thêm hai chỉ thị retract vào go.mod, sau đó gắn thẻ v1.0.1 với các lần thu hồi.
retract (
v1.0.0 // Được xuất bản do nhầm lẫn.
v1.0.1 // Chỉ chứa các lần thu hồi.
)
Khi người dùng chạy go get example.com/m@latest, lệnh go đọc các lần thu hồi từ v1.0.1, hiện là phiên bản cao nhất. Cả v1.0.0 và v1.0.1 đều bị thu hồi, vì vậy lệnh go sẽ nâng cấp (hoặc hạ cấp!) xuống phiên bản cao nhất tiếp theo, có thể là v0.9.5.
Các chỉ thị retract có thể được viết với một phiên bản duy nhất (như v1.0.0) hoặc với một khoảng đóng của các phiên bản có giới hạn trên và giới hạn dưới, được phân cách bằng [ và ] (như [v1.1.0, v1.2.0]). Một phiên bản duy nhất tương đương với một khoảng mà giới hạn trên và giới hạn dưới giống nhau. Giống như các chỉ thị khác, nhiều chỉ thị retract có thể được nhóm lại trong một khối được phân cách bởi ( ở cuối dòng và ) trên một dòng riêng.
Mỗi chỉ thị retract nên có một chú thích giải thích lý do thu hồi, dù điều này không bắt buộc. Lệnh go có thể hiển thị các chú thích lý do trong cảnh báo về các phiên bản bị thu hồi và trong đầu ra của go list. Chú thích lý do có thể được viết ngay phía trên một chỉ thị retract (không có dòng trống ở giữa) hoặc sau đó trên cùng dòng. Nếu một chú thích xuất hiện phía trên một khối, nó áp dụng cho tất cả các chỉ thị retract trong khối không có chú thích riêng. Một chú thích lý do có thể trải dài trên nhiều dòng.
RetractDirective = "retract" ( RetractSpec | "(" newline { RetractSpec } ")" newline ) .
RetractSpec = ( Version | "[" Version "," Version "]" ) newline .
Ví dụ:
- Thu hồi tất cả phiên bản giữa
v1.0.0vàv1.9.9:
retract v1.0.0
retract [v1.0.0, v1.9.9]
retract (
v1.0.0
[v1.0.0, v1.9.9]
)
- Trở về trạng thái không có phiên bản sau khi phát hành sớm một phiên bản
v1.0.0:
retract [v0.0.0, v1.0.1] // giả sử v1.0.1 chứa lần thu hồi này.
- Xóa một module bao gồm tất cả pseudo-version và phiên bản được gắn thẻ:
retract [v0.0.0-0, v0.15.2] // giả sử v0.15.2 chứa lần thu hồi này.
Chỉ thị retract được thêm vào trong Go 1.16. Go 1.15 trở xuống sẽ báo lỗi nếu một chỉ thị retract được viết trong tệp go.mod của main
module và sẽ bỏ qua các chỉ thị retract trong các tệp go.mod của dependency.
Cập nhật tự động
Hầu hết các lệnh đều báo lỗi nếu go.mod thiếu thông tin hoặc không phản ánh chính xác thực tế. Các lệnh go get và
go mod tidy có thể được sử dụng để khắc phục phần lớn các vấn đề này. Ngoài ra, cờ -mod=mod có thể được dùng với hầu hết các lệnh nhận biết module (go build, go test, v.v.) để yêu cầu lệnh go tự động khắc phục các vấn đề trong go.mod và go.sum.
Ví dụ, hãy xem xét tệp go.mod này:
module example.com/M
go 1.23.0
require (
example.com/A v1
example.com/B v1.0.0
example.com/C v1.0.0
example.com/D v1.2.3
example.com/E dev
)
exclude example.com/D v1.2.3
Bản cập nhật được kích hoạt với -mod=mod sẽ viết lại các mã định danh phiên bản không chuẩn về dạng semver chuẩn, vì vậy v1 của example.com/A trở thành v1.0.0, và dev của example.com/E trở thành phiên bản giả cho commit mới nhất trên nhánh dev, có thể là v0.0.0-20180523231146-b3f5c0f6e5f1.
Bản cập nhật sửa đổi các yêu cầu để tuân theo các loại trừ, vì vậy yêu cầu đối với example.com/D v1.2.3 đã bị loại trừ được cập nhật để sử dụng phiên bản tiếp theo có sẵn của example.com/D, có thể là v1.2.4 hoặc v1.3.0.
Bản cập nhật loại bỏ các yêu cầu dư thừa hoặc gây hiểu nhầm. Ví dụ, nếu bản thân example.com/A v1.0.0 yêu cầu example.com/B v1.2.0 và example.com/C v1.0.0, thì yêu cầu của go.mod đối với example.com/B v1.0.0 là gây hiểu nhầm (đã bị thay thế bởi nhu cầu v1.2.0 của example.com/A), và yêu cầu của nó đối với example.com/C v1.0.0 là dư thừa (được suy ra từ nhu cầu cùng phiên bản của example.com/A), vì vậy cả hai sẽ bị loại bỏ. Nếu module chính chứa các gói nhập trực tiếp các gói từ example.com/B hoặc example.com/C, thì các yêu cầu sẽ được giữ lại nhưng được cập nhật thành các phiên bản thực tế đang được sử dụng.
Cuối cùng, bản cập nhật định dạng lại go.mod theo định dạng chuẩn, để các thay đổi cơ học trong tương lai sẽ tạo ra các diff tối thiểu. Lệnh go sẽ không cập nhật go.mod nếu chỉ cần thay đổi định dạng.
Vì đồ thị module xác định ý nghĩa của các câu lệnh import, mọi lệnh tải gói cũng sử dụng go.mod và do đó có thể cập nhật nó, bao gồm go build, go get, go install, go list, go test, go mod tidy.
Trong Go 1.15 trở xuống, cờ -mod=mod được bật theo mặc định, vì vậy các bản cập nhật được thực hiện tự động. Kể từ Go 1.16, lệnh go hoạt động như thể -mod=readonly được đặt thay thế: nếu cần bất kỳ thay đổi nào đối với go.mod, lệnh go sẽ báo lỗi và đề xuất cách khắc phục.
Lựa chọn phiên bản tối thiểu (MVS)
Go sử dụng một thuật toán có tên là Lựa chọn phiên bản tối thiểu (MVS) để chọn một tập hợp các phiên bản module được sử dụng khi xây dựng các gói. MVS được mô tả chi tiết trong Minimal Version Selection của Russ Cox.
Về mặt khái niệm, MVS hoạt động trên một đồ thị có hướng của các module, được chỉ định bằng các tệp go.mod. Mỗi đỉnh trong đồ thị biểu diễn một phiên bản module. Mỗi cạnh biểu diễn phiên bản tối thiểu được yêu cầu của một dependency, được chỉ định bằng một chỉ thị require. Đồ thị có thể được sửa đổi bởi các chỉ thị exclude và replace trong (các) tệp go.mod của (các) module chính và bởi các chỉ thị replace trong tệp go.work.
MVS tạo ra danh sách build làm đầu ra, là danh sách các phiên bản module được sử dụng cho một bản build.
MVS bắt đầu từ các module chính (các đỉnh đặc biệt trong đồ thị không có phiên bản) và duyệt qua đồ thị, theo dõi phiên bản được yêu cầu cao nhất của từng module. Khi kết thúc quá trình duyệt, các phiên bản được yêu cầu cao nhất tạo thành danh sách build: chúng là các phiên bản tối thiểu đáp ứng mọi yêu cầu.
Có thể kiểm tra danh sách build bằng lệnh go list -m all. Không giống các hệ thống quản lý dependency khác, danh sách build không được lưu trong tệp “lock”. MVS có tính xác định, và danh sách build không thay đổi khi các phiên bản mới của dependency được phát hành, vì vậy MVS được dùng để tính toán danh sách này ở đầu mỗi lệnh nhận biết module.
Hãy xem ví dụ trong sơ đồ bên dưới. Module chính yêu cầu module A ở phiên bản 1.2 trở lên và module B ở phiên bản 1.2 trở lên. A 1.2 và B 1.2 lần lượt yêu cầu C 1.3 và C 1.4. C 1.3 và C 1.4 đều yêu cầu D 1.2.
MVS truy cập và tải tệp go.mod cho từng phiên bản module được đánh dấu màu xanh lam. Khi kết thúc quá trình duyệt đồ thị, MVS trả về một danh sách build chứa các phiên bản được in đậm: A 1.2, B 1.2, C 1.4 và D 1.2. Lưu ý rằng các phiên bản cao hơn của B và D có sẵn nhưng MVS không chọn chúng, vì không có gì yêu cầu chúng.
Thay thế
Nội dung của một module (bao gồm tệp go.mod của nó) có thể được thay thế bằng chỉ thị replace trong tệp go.mod của module chính hoặc tệp go.work của một workspace. Một chỉ thị replace có thể áp dụng cho một phiên bản cụ thể của một module hoặc cho tất cả phiên bản của một module.
Các thay thế làm thay đổi đồ thị module, vì một module thay thế có thể có các dependency khác với các phiên bản bị thay thế.
Xét ví dụ bên dưới, trong đó C 1.4 đã được thay thế bằng R. R phụ thuộc vào D 1.3 thay vì D 1.2, vì vậy MVS trả về danh sách build chứa A 1.2, B 1.2, C 1.4 (được thay thế bằng R) và D 1.3.
Loại trừ
Một module cũng có thể bị loại trừ ở các phiên bản cụ thể bằng chỉ thị exclude trong tệp go.mod của module chính.
Các loại trừ cũng làm thay đổi đồ thị module. Khi một phiên bản bị loại trừ, nó sẽ bị xóa khỏi đồ thị module, và các yêu cầu đối với nó được chuyển hướng đến phiên bản cao hơn tiếp theo.
Xét ví dụ bên dưới. C 1.3 đã bị loại trừ. MVS sẽ hoạt động như thể A 1.2 yêu cầu C 1.4 (phiên bản cao hơn tiếp theo) thay vì C 1.3.
Nâng cấp
Lệnh go get có thể được dùng để nâng cấp một tập hợp module. Để thực hiện nâng cấp, lệnh go thay đổi đồ thị module trước khi chạy MVS bằng cách thêm các cạnh từ các phiên bản đã duyệt đến các phiên bản đã nâng cấp.
Xét ví dụ bên dưới. Module B có thể được nâng cấp từ 1.2 lên 1.3, C có thể được nâng cấp từ 1.3 lên 1.4, và D có thể được nâng cấp từ 1.2 lên 1.3.
Các nâng cấp (và hạ cấp) có thể thêm hoặc xóa các dependency gián tiếp. Trong trường hợp này, E 1.1 và F 1.1 xuất hiện trong danh sách build sau khi nâng cấp, vì E 1.1 được B 1.3 yêu cầu.
Để duy trì các nâng cấp, lệnh go cập nhật các yêu cầu trong go.mod. Nó sẽ thay đổi yêu cầu đối với B thành phiên bản 1.3. Nó cũng sẽ thêm các yêu cầu đối với C 1.4 và D 1.3 với các chú thích // indirect, vì nếu không thì các phiên bản đó sẽ không được chọn.
Hạ cấp
Lệnh go get cũng có thể được dùng để hạ cấp một tập hợp module. Để thực hiện việc hạ cấp, lệnh go thay đổi đồ thị module bằng cách loại bỏ các phiên bản cao hơn những phiên bản được hạ cấp. Lệnh này cũng loại bỏ các phiên bản của những module khác phụ thuộc vào các phiên bản đã bị loại bỏ, vì chúng có thể không tương thích với các phiên bản đã hạ cấp của dependency của chúng. Nếu module chính yêu cầu một phiên bản module bị loại bỏ do hạ cấp, yêu cầu đó được thay đổi thành một phiên bản trước đó chưa bị loại bỏ. Nếu không có phiên bản trước đó, yêu cầu sẽ bị loại bỏ.
Hãy xem xét ví dụ bên dưới. Giả sử phát hiện một vấn đề với C 1.4, vì vậy chúng ta hạ cấp xuống C 1.3. C 1.4 bị loại bỏ khỏi đồ thị module. B 1.2 cũng bị loại bỏ vì nó yêu cầu C 1.4 trở lên. Yêu cầu của module chính đối với B được thay đổi thành 1.1.
go get cũng có thể loại bỏ hoàn toàn các dependency bằng cách sử dụng hậu tố @none sau một đối số. Cách này hoạt động tương tự như hạ cấp. Tất cả phiên bản của module được chỉ định đều bị loại bỏ khỏi đồ thị module.
Cắt tỉa đồ thị module
Nếu module chính ở go 1.17 trở lên, đồ thị module được dùng cho lựa chọn phiên bản tối thiểu chỉ bao gồm các yêu cầu trực tiếp đối với từng dependency module chỉ định go 1.17 trở lên trong tệp go.mod của chính nó, trừ khi phiên bản đó của module cũng được một dependency khác tại go 1.16 trở xuống yêu cầu (theo cách bắc cầu). (Các dependency bắc cầu của các dependency go 1.17 được cắt bỏ khỏi đồ thị module.)
Vì tệp go.mod của go 1.17 bao gồm một chỉ thị require cho mọi dependency cần thiết để xây dựng bất kỳ package hoặc bài kiểm thử nào trong module đó, đồ thị module đã được cắt tỉa bao gồm tất cả dependency cần thiết để go build hoặc go test các package trong bất kỳ dependency nào được module chính yêu cầu rõ ràng. Một module không cần thiết để xây dựng bất kỳ package hoặc bài kiểm thử nào trong một module cụ thể không thể ảnh hưởng đến hành vi thời gian chạy của các package trong module đó, vì vậy các dependency bị cắt khỏi đồ thị module chỉ gây ra sự can thiệp giữa các module vốn không liên quan.
Các module có yêu cầu đã bị cắt tỉa vẫn xuất hiện trong đồ thị module và vẫn được go list -m all báo cáo: phiên bản được chọn của chúng đã được biết và xác định rõ ràng, và các package có thể được tải từ những module đó (ví dụ, dưới dạng dependency bắc cầu của các bài kiểm thử được tải từ các module khác). Tuy nhiên, vì lệnh go không thể dễ dàng xác định dependency nào của các module này được thỏa mãn, các đối số của go build và go test không thể bao gồm package từ các module có yêu cầu đã bị cắt tỉa. go get nâng module chứa mỗi package được chỉ định thành một dependency rõ ràng, cho phép gọi go build hoặc go test trên package đó.
Vì Go 1.16 và các phiên bản trước đó không hỗ trợ cắt tỉa đồ thị module, toàn bộ bao đóng bắc cầu của các dependency — bao gồm cả các dependency go 1.17 bắc cầu — vẫn được bao gồm cho mỗi module chỉ định go 1.16 trở xuống. (Ở go 1.16 trở xuống, tệp go.mod chỉ bao gồm dependency trực tiếp, vì vậy phải tải một đồ thị lớn hơn nhiều để đảm bảo tất cả dependency gián tiếp được bao gồm.)
Tệp go.sum được ghi bởi go mod tidy cho một module theo mặc định bao gồm các checksum cần thiết bởi phiên bản Go thấp hơn một phiên bản so với phiên bản được chỉ định trong chỉ thị go của nó. Vì vậy, một module go 1.17 bao gồm các checksum cần thiết cho toàn bộ đồ thị module được Go 1.16 tải, nhưng một module go 1.18 sẽ chỉ bao gồm các checksum cần thiết cho đồ thị module đã được cắt tỉa được Go 1.17 tải. Cờ -compat có thể được dùng để ghi đè phiên bản mặc định (ví dụ, để cắt tỉa tệp go.sum mạnh hơn trong module go 1.17).
Xem tài liệu thiết kế để biết thêm chi tiết.
Tải module lười
Các yêu cầu toàn diện hơn được bổ sung cho việc cắt tỉa đồ thị module cũng cho phép một tối ưu hóa khác khi làm việc trong một module. Nếu module chính ở mức go 1.17 trở lên, lệnh go tránh tải toàn bộ đồ thị module cho đến khi (và trừ khi) cần đến nó. Thay vào đó, nó chỉ tải tệp go.mod của module chính, sau đó cố gắng tải các gói cần được xây dựng chỉ bằng các yêu cầu đó. Nếu không tìm thấy một gói cần import (ví dụ: một dependency của một bài kiểm thử cho một gói bên ngoài module chính) trong các yêu cầu đó, thì phần còn lại của đồ thị module sẽ được tải theo yêu cầu.
Nếu tất cả các gói được import có thể được tìm thấy mà không cần tải đồ thị module, thì lệnh go sau đó chỉ tải các tệp go.mod của các module chứa những gói đó, và các yêu cầu của chúng được kiểm tra với các yêu cầu của module chính để đảm bảo rằng chúng nhất quán cục bộ. (Sự không nhất quán có thể phát sinh do việc hợp nhất trong kiểm soát phiên bản, chỉnh sửa thủ công và các thay đổi trong các module đã được thay thế bằng cách sử dụng đường dẫn hệ thống tệp cục bộ.)
Workspace
Một workspace là một tập hợp các module trên đĩa được sử dụng làm các module chính khi chạy minimal version selection (MVS).
Một workspace có thể được khai báo trong tệp go.work, tệp này chỉ định các đường dẫn tương đối đến thư mục module của từng module trong workspace. Khi không tồn tại tệp go.work, workspace bao gồm một module duy nhất chứa thư mục hiện tại.
Hầu hết các lệnh con go làm việc với các module hoạt động trên tập hợp các module được xác định bởi workspace hiện tại. go mod init, go mod why, go mod edit, go mod tidy, go mod vendor và go get luôn hoạt động trên một module chính duy nhất.
Một lệnh xác định liệu nó có đang ở trong ngữ cảnh workspace hay không bằng cách trước tiên kiểm tra biến môi trường GOWORK. Nếu GOWORK được đặt thành off, lệnh sẽ ở trong ngữ cảnh một module duy nhất. Nếu biến này rỗng hoặc không được cung cấp, lệnh sẽ tìm kiếm tệp go.work trong thư mục làm việc hiện tại, sau đó trong các thư mục cha liên tiếp. Nếu tìm thấy một tệp, lệnh sẽ hoạt động trong workspace mà tệp đó định nghĩa; nếu không, workspace sẽ chỉ bao gồm module chứa thư mục làm việc.
Nếu GOWORK đặt tên một đường dẫn đến một tệp hiện có kết thúc bằng .work, chế độ workspace sẽ được bật. Mọi giá trị khác đều là lỗi. Bạn có thể sử dụng lệnh go env GOWORK để xác định tệp go.work nào mà lệnh go đang sử dụng. go env GOWORK sẽ rỗng nếu lệnh go không ở chế độ workspace.
go.work files
Một workspace được xác định bởi một tệp văn bản được mã hóa UTF-8 có tên go.work. Tệp
go.work có cấu trúc theo dòng. Mỗi dòng chứa một chỉ thị duy nhất, gồm một
từ khóa theo sau bởi các đối số. Ví dụ:
go 1.23.0
use ./my/first/thing
use ./my/second/thing
replace example.com/bad/thing v1.4.5 => example.com/good/thing v1.4.5
Tương tự như các tệp go.mod, một từ khóa ở đầu có thể được tách ra khỏi các dòng
liền kề để tạo thành một khối.
use (
./my/first/thing
./my/second/thing
)
Lệnh go cung cấp một số lệnh con để thao tác với các tệp go.work.
go work init tạo các tệp go.work mới. go work use thêm các thư mục module vào
tệp go.work. go work edit thực hiện các chỉnh sửa
cấp thấp. Gói
golang.org/x/mod/modfile
có thể được các chương trình Go sử dụng để thực hiện các thay đổi tương tự bằng mã.
Lệnh go sẽ duy trì một tệp go.work.sum để theo dõi các hash được workspace sử dụng
nhưng không có trong các tệp go.sum của các module workspace tập hợp.
Thông thường không nên commit các tệp go.work vào các hệ thống kiểm soát phiên bản, vì hai lý do:
- Một tệp
go.workđược đưa vào kho có thể ghi đè lên tệpgo.workriêng của nhà phát triển từ thư mục cha, gây nhầm lẫn khi các chỉ thịusecủa họ không được áp dụng. - Một tệp
go.workđược đưa vào kho có thể khiến hệ thống tích hợp liên tục (CI) chọn và do đó kiểm thử sai các phiên bản dependency của một module. Các hệ thống CI nhìn chung không nên được phép sử dụng tệpgo.workđể chúng có thể kiểm thử hành vi của module như khi module đó được các module khác yêu cầu, trong trường hợp này tệpgo.workbên trong module không có tác dụng.
Tuy nhiên, có một số trường hợp việc commit một tệp go.work là hợp lý.
Ví dụ, khi các module trong một repository được phát triển riêng biệt với
nhau nhưng không cùng với các module bên ngoài, có thể không có lý do để
nhà phát triển muốn sử dụng một tổ hợp module khác trong một workspace.
Trong trường hợp đó, tác giả module nên đảm bảo các module riêng lẻ được kiểm thử
và phát hành đúng cách.
Các phần tử từ vựng
Các phần tử từ vựng trong tệp go.work được định nghĩa hoàn toàn giống như đối với go.mod files.
Ngữ pháp
Cú pháp go.work được chỉ định bên dưới bằng cách sử dụng Dạng Backus-Naur mở rộng (EBNF).
Xem phần Ký hiệu trong Đặc tả Ngôn ngữ Go để biết chi tiết về cú pháp EBNF.
GoWork = { Directive } .
Directive = GoDirective |
ToolchainDirective |
UseDirective |
ReplaceDirective .
Dòng mới, định danh và chuỗi lần lượt được biểu diễn bằng newline, ident và string.
Đường dẫn module và phiên bản được biểu diễn bằng ModulePath và Version.
Đường dẫn module và phiên bản được chỉ định hoàn toàn giống như đối với go.mod files.
ModulePath = ident | string . /* xem các hạn chế ở trên */
Version = ident | string . /* xem các hạn chế ở trên */
Chỉ thị go
Chỉ thị go là bắt buộc trong một tệp go.work hợp lệ. Phiên bản phải là một phiên bản Go bản phát hành hợp lệ: một số nguyên dương theo sau bởi dấu chấm và một số nguyên không âm (ví dụ: 1.18, 1.19).
Chỉ thị go cho biết phiên bản chuỗi công cụ go mà tệp go.work được thiết kế để hoạt động cùng. Nếu có thay đổi đối với định dạng tệp go.work, các phiên bản tương lai của chuỗi công cụ sẽ diễn giải tệp dựa theo phiên bản được chỉ định.
Một tệp go.work có thể chứa nhiều nhất một chỉ thị go.
GoDirective = "go" GoVersion newline .
GoVersion = string | ident . /* phiên bản Go bản phát hành hợp lệ; xem ở trên */
Ví dụ:
go 1.23.0
Chỉ thị toolchain
Chỉ thị toolchain khai báo một chuỗi công cụ Go được đề xuất để sử dụng trong một workspace.
Chỉ thị này chỉ có hiệu lực khi chuỗi công cụ mặc định cũ hơn chuỗi công cụ được đề xuất.
Để biết chi tiết, xem “Chuỗi công cụ Go”.
ToolchainDirective = "toolchain" ToolchainName newline .
ToolchainName = string | ident . /* tên chuỗi công cụ hợp lệ; xem “Chuỗi công cụ Go” */
Ví dụ:
toolchain go1.21.0
godebug directive
Chỉ thị godebug khai báo một thiết lập GODEBUG duy nhất
để áp dụng khi làm việc trong workspace này.
Cú pháp và tác động giống với chỉ thị godebug của tệp go.mod.
Khi một workspace đang được sử dụng, các chỉ thị godebug trong các tệp go.mod sẽ bị bỏ qua.
use directive
Một use thêm một module trên đĩa vào tập hợp các module chính trong một workspace.
Đối số của nó là một đường dẫn tương đối đến thư mục chứa tệp
go.mod của module. Chỉ thị use không thêm các module nằm trong
các thư mục con của thư mục được chỉ định. Các module đó có thể được thêm bởi
thư mục chứa tệp go.mod của chúng trong các chỉ thị use riêng biệt.
UseDirective = "use" ( UseSpec | "(" newline { UseSpec } ")" newline ) .
UseSpec = FilePath newline .
FilePath = /* platform-specific relative or absolute file path */
Ví dụ:
use ./mymod // example.com/mymod
use (
../othermod
./subdir/thirdmod
)
replace directive
Tương tự như chỉ thị replace trong tệp go.mod, chỉ thị replace trong
tệp go.work thay thế nội dung của một phiên bản cụ thể của một module,
hoặc tất cả các phiên bản của một module, bằng nội dung được tìm thấy ở nơi khác. Một thay thế
ký tự đại diện trong go.work ghi đè lên một replace dành riêng cho phiên bản trong tệp go.mod.
Các chỉ thị replace trong các tệp go.work ghi đè mọi thay thế của cùng
module hoặc phiên bản module trong các module thuộc workspace.
ReplaceDirective = "replace" ( ReplaceSpec | "(" newline { ReplaceSpec } ")" newline ) .
ReplaceSpec = ModulePath [ Version ] "=>" FilePath newline
| ModulePath [ Version ] "=>" ModulePath Version newline .
FilePath = /* platform-specific relative or absolute file path */
Ví dụ:
replace golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
replace (
golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5
golang.org/x/net => example.com/fork/net v1.4.5
golang.org/x/net v1.2.3 => ./fork/net
golang.org/x/net => ./fork/net
)
Khả năng tương thích với các kho lưu trữ không sử dụng module
Để đảm bảo quá trình chuyển đổi suôn sẻ từ GOPATH sang module, lệnh go có thể tải xuống và xây dựng các gói ở chế độ nhận biết module từ các kho lưu trữ chưa di chuyển sang module bằng cách thêm một tệp go.mod.
Khi lệnh go tải xuống một module ở một phiên bản cụ thể trực tiếp từ một kho lưu trữ, nó tìm URL kho lưu trữ cho đường dẫn module, ánh xạ phiên bản tới một revision trong kho lưu trữ, sau đó trích xuất một bản lưu trữ của kho lưu trữ tại revision đó. Nếu đường dẫn của module bằng với đường dẫn gốc của kho lưu trữ, và thư mục gốc của kho lưu trữ không chứa tệp go.mod, lệnh go tạo tổng hợp một tệp go.mod trong bộ nhớ đệm module chứa chỉ thị module và không có gì khác. Vì các tệp go.mod tổng hợp không chứa các chỉ thị require cho các dependency của chúng, các module khác phụ thuộc vào chúng có thể cần thêm các chỉ thị require (với các chú thích // indirect) để đảm bảo mỗi dependency được tải ở cùng một phiên bản trong mọi lần xây dựng.
Khi lệnh go tải xuống một module từ một proxy, nó tải tệp go.mod riêng biệt với phần nội dung còn lại của module. Proxy được kỳ vọng sẽ cung cấp một tệp go.mod tổng hợp nếu module ban đầu không có tệp này.
Các phiên bản +incompatible
Một module được phát hành ở phiên bản major 2 trở lên phải có hậu tố phiên bản major tương ứng trên đường dẫn module của nó. Ví dụ, nếu một module được phát hành ở v2.0.0, đường dẫn của nó phải có hậu tố /v2. Điều này cho phép lệnh go xem nhiều phiên bản major của một dự án là các module riêng biệt, ngay cả khi chúng được phát triển trong cùng một kho lưu trữ.
Yêu cầu về hậu tố phiên bản major được đưa ra khi hỗ trợ module được thêm vào lệnh go, và nhiều kho lưu trữ đã gắn thẻ các bản phát hành với phiên bản major 2 hoặc cao hơn trước thời điểm đó. Để duy trì khả năng tương thích với các kho lưu trữ này, lệnh go thêm hậu tố +incompatible vào các phiên bản có phiên bản major 2 trở lên mà không có tệp go.mod. +incompatible cho biết một phiên bản là một phần của cùng module với các phiên bản có số phiên bản major thấp hơn; do đó, lệnh go có thể tự động nâng cấp lên các phiên bản +incompatible cao hơn mặc dù điều đó có thể làm hỏng quá trình xây dựng.
Xem xét yêu cầu ví dụ dưới đây:
require example.com/m v4.1.2+incompatible
Phiên bản v4.1.2+incompatible tham chiếu đến thẻ phiên bản ngữ nghĩa v4.1.2 trong kho lưu trữ cung cấp module example.com/m. Module phải nằm trong thư mục gốc của kho lưu trữ (nghĩa là đường dẫn gốc của kho lưu trữ cũng phải là example.com/m), và không được có tệp go.mod. Module có thể có các phiên bản với số phiên bản major thấp hơn như v1.5.2, và lệnh go có thể tự động nâng cấp lên v4.1.2+incompatible từ các phiên bản đó (xem lựa chọn phiên bản tối thiểu (MVS) để biết thông tin về cách hoạt động của việc nâng cấp).
Một kho lưu trữ di chuyển sang module sau khi phiên bản v2.0.0 được gắn thẻ thường nên phát hành một phiên bản major mới. Trong ví dụ trên, tác giả nên tạo một module với đường dẫn example.com/m/v5 và nên phát hành phiên bản v5.0.0. Tác giả cũng nên cập nhật các import của các gói trong module để sử dụng tiền tố example.com/m/v5 thay vì example.com/m. Xem Go Modules: v2 and Beyond để có ví dụ chi tiết hơn.
Lưu ý rằng hậu tố +incompatible không nên xuất hiện trên một thẻ trong kho lưu trữ; một thẻ như v4.1.2+incompatible sẽ bị bỏ qua. Hậu tố này chỉ xuất hiện trong các phiên bản được lệnh go sử dụng. Xem Ánh xạ phiên bản tới các commit để biết chi tiết về sự khác biệt giữa phiên bản và thẻ.
Cũng lưu ý rằng hậu tố +incompatible có thể xuất hiện trên các phiên bản giả. Ví dụ, v2.0.1-20200722182040-012345abcdef+incompatible có thể là một phiên bản giả hợp lệ.
Tương thích module tối thiểu
Một module được phát hành ở phiên bản chính 2 trở lên bắt buộc phải có hậu tố phiên bản chính trong đường dẫn module của nó. Module có thể được phát triển hoặc không được phát triển trong một thư mục con phiên bản chính bên trong kho lưu trữ của nó. Điều này ảnh hưởng đến các gói nhập các gói bên trong module khi xây dựng ở chế độ GOPATH.
Thông thường trong chế độ GOPATH, một gói được lưu trong một thư mục khớp với đường dẫn gốc của kho lưu trữ của nó, nối với thư mục của gói đó bên trong kho lưu trữ. Ví dụ: một gói trong kho lưu trữ có đường dẫn gốc example.com/repo ở thư mục con sub sẽ được lưu trong $GOPATH/src/example.com/repo/sub và được nhập bằng example.com/repo/sub.
Đối với một module có hậu tố phiên bản chính, có thể mong đợi tìm thấy gói example.com/repo/v2/sub trong thư mục $GOPATH/src/example.com/repo/v2/sub. Điều này yêu cầu module được phát triển trong thư mục con v2 của kho lưu trữ. Lệnh go hỗ trợ điều này nhưng không yêu cầu như vậy (xem Ánh xạ phiên bản tới các commit).
Nếu một module không được phát triển trong thư mục con phiên bản chính, thì thư mục của nó trong GOPATH sẽ không chứa hậu tố phiên bản chính, và các gói của nó có thể được nhập mà không có hậu tố phiên bản chính. Trong ví dụ trên, gói sẽ được tìm thấy trong thư mục $GOPATH/src/example.com/repo/sub và được nhập bằng example.com/repo/sub.
Điều này tạo ra một vấn đề cho các gói được dự định xây dựng trong cả chế độ module và chế độ GOPATH: chế độ module yêu cầu hậu tố, trong khi chế độ GOPATH thì không.
Để khắc phục điều này, tương thích module tối thiểu đã được thêm vào Go 1.11 và được backport về Go 1.9.7 và 1.10.3. Khi đường dẫn nhập được phân giải thành một thư mục trong chế độ GOPATH:
- Khi phân giải một import có dạng
$modpath/$vn/$dirtrong đó:$modpathlà một đường dẫn module hợp lệ,$vnlà một hậu tố phiên bản chính,$dirlà một thư mục con có thể rỗng,
- Nếu tất cả các điều kiện sau đều đúng:
- Gói
$modpath/$vn/$dirkhông có trong bất kỳ thư mụcvendorliên quan nào. - Tệp
go.modcó trong cùng thư mục với tệp đang nhập hoặc trong bất kỳ thư mục cha nào cho đến thư mục gốc$GOPATH/src, - Không tồn tại thư mục
$GOPATH[i]/src/$modpath/$vn/$suffix(với bất kỳ thư mục gốc$GOPATH[i]nào), - Tệp
$GOPATH[d]/src/$modpath/go.modtồn tại (với một thư mục gốc$GOPATH[d]nào đó) và khai báo đường dẫn module là$modpath/$vn,
- Gói
- Khi đó import
$modpath/$vn/$dirđược phân giải thành thư mục$GOPATH[d]/src/$modpath/$dir.
Quy tắc này cho phép các gói đã được chuyển sang module nhập các gói khác đã được chuyển sang module khi được xây dựng trong chế độ GOPATH, ngay cả khi không sử dụng thư mục con phiên bản chính.
Các lệnh nhận biết module
Hầu hết các lệnh go có thể chạy ở chế độ nhận biết module hoặc chế độ GOPATH. Ở chế độ nhận biết module, lệnh go sử dụng các tệp go.mod để tìm các dependency có phiên bản, và thường tải các gói từ bộ nhớ đệm module, tải xuống các module nếu chúng chưa có. Ở chế độ GOPATH, lệnh go bỏ qua các module; nó tìm dependency trong các thư mục vendor và trong GOPATH.
Kể từ Go 1.16, chế độ nhận biết module được bật theo mặc định, bất kể có tệp go.mod hay không. Ở các phiên bản thấp hơn, chế độ nhận biết module được bật khi có tệp go.mod trong thư mục hiện tại hoặc bất kỳ thư mục cha nào.
Chế độ nhận biết module có thể được điều khiển bằng biến môi trường GO111MODULE, có thể được đặt thành on, off hoặc auto.
- Nếu
GO111MODULE=off, lệnhgobỏ qua các tệpgo.modvà chạy ở chế độGOPATH. - Nếu
GO111MODULE=onhoặc không được đặt, lệnhgochạy ở chế độ nhận biết module, ngay cả khi không có tệpgo.mod. Không phải tất cả lệnh đều hoạt động khi không có tệpgo.mod: xem Các lệnh module bên ngoài một module. - Nếu
GO111MODULE=auto, lệnhgochạy ở chế độ nhận biết module nếu có tệpgo.modtrong thư mục hiện tại hoặc bất kỳ thư mục cha nào. Trong Go 1.15 trở xuống, đây là hành vi mặc định. Các lệnh congo modvàgo installvới truy vấn phiên bản chạy ở chế độ nhận biết module ngay cả khi không có tệpgo.mod.
Ở chế độ nhận biết module, GOPATH không còn xác định ý nghĩa của các import trong quá trình build, nhưng nó vẫn lưu các dependency đã tải xuống (trong GOPATH/pkg/mod; xem Bộ nhớ đệm module) và các lệnh đã cài đặt (trong GOPATH/bin, trừ khi GOBIN được đặt).
Các lệnh build
Tất cả các lệnh tải thông tin về gói đều nhận biết module. Bao gồm:
go buildgo fixgo generatego installgo listgo rungo testgo vet
Khi chạy ở chế độ nhận biết module, các lệnh này sử dụng các tệp go.mod để diễn giải đường dẫn import được liệt kê trên dòng lệnh hoặc được viết trong các tệp mã nguồn Go. Các lệnh này chấp nhận các cờ sau, dùng chung cho tất cả các lệnh module.
- Cờ
-modđiều khiển việcgo.modcó thể được tự động cập nhật hay không và thư mụcvendorcó được sử dụng hay không.-mod=modyêu cầu lệnhgobỏ qua thư mục vendor và tự động cập nhậtgo.mod, ví dụ khi một gói được import không được cung cấp bởi bất kỳ module đã biết nào.-mod=readonlyyêu cầu lệnhgobỏ qua thư mụcvendorvà báo lỗi nếugo.modcần được cập nhật.-mod=vendoryêu cầu lệnhgosử dụng thư mụcvendor. Ở chế độ này, lệnhgosẽ không sử dụng mạng hoặc bộ nhớ đệm module.- Theo mặc định, nếu phiên bản
gotronggo.modlà1.14trở lên và có thư mụcvendor, lệnhgohoạt động như thể-mod=vendorđược sử dụng. Nếu không, lệnhgohoạt động như thể-mod=readonlyđược sử dụng. go gettừ chối cờ này vì mục đích của lệnh là sửa đổi dependency, việc này chỉ được cho phép bởi-mod=mod.
- Cờ
-modcacherwyêu cầu lệnhgotạo các thư mục mới trong bộ nhớ đệm module với quyền đọc-ghi thay vì chỉ đọc. Khi cờ này được sử dụng nhất quán (thường bằng cách đặtGOFLAGS=-modcacherwtrong môi trường hoặc chạygo env -w GOFLAGS=-modcacherw), bộ nhớ đệm module có thể được xóa bằng các lệnh nhưrm -rmà không cần thay đổi quyền trước. Lệnhgo clean -modcachecó thể được dùng để xóa bộ nhớ đệm module, bất kể có sử dụng-modcacherwhay không. - Cờ
-modfile=file.modyêu cầu lệnhgođọc (và có thể ghi) một tệp thay thế thay chogo.modtrong thư mục gốc của module. Tên tệp phải kết thúc bằng.mod. Vẫn phải có một tệp tên làgo.modđể xác định thư mục gốc của module, nhưng tệp này không được truy cập. Khi-modfileđược chỉ định, một tệpgo.sumthay thế cũng được sử dụng: đường dẫn của nó được suy ra từ cờ-modfilebằng cách loại bỏ phần mở rộng.modvà thêm.sum.
Vendoring
Khi sử dụng module, lệnh go thường thỏa mãn các dependency bằng cách tải xuống các module từ nguồn của chúng vào bộ nhớ đệm module, sau đó tải các gói từ các bản sao đã tải xuống đó. Vendoring có thể được sử dụng để cho phép tương tác với các phiên bản Go cũ hơn, hoặc để đảm bảo rằng tất cả tệp được sử dụng cho một bản build được lưu trữ trong một cây tệp duy nhất.
Lệnh go mod vendor tạo một thư mục có tên vendor trong thư mục gốc của module chính, chứa các bản sao của tất cả gói cần thiết để build và kiểm thử các gói trong module chính. Các gói chỉ được import bởi các bài kiểm thử của gói bên ngoài module chính sẽ không được đưa vào. Giống như go mod tidy và các lệnh module khác, ràng buộc build ngoại trừ ignore không được xem xét khi tạo thư mục vendor.
go mod vendor cũng tạo tệp vendor/modules.txt, chứa danh sách các gói được vendoring và các phiên bản module mà chúng được sao chép từ đó. Khi vendoring được bật, tệp kê khai này được sử dụng làm nguồn thông tin phiên bản module, như được báo cáo bởi go list -m và go version -m. Khi lệnh go đọc vendor/modules.txt, lệnh này kiểm tra rằng các phiên bản module nhất quán với go.mod. Nếu go.mod đã thay đổi kể từ khi vendor/modules.txt được tạo, lệnh go sẽ báo lỗi. Cần chạy lại go mod vendor để cập nhật thư mục vendor.
Nếu thư mục vendor tồn tại trong thư mục gốc của module chính, thư mục này sẽ được tự động sử dụng nếu phiên bản go trong tệp go.mod của module chính là 1.14 hoặc cao hơn. Để bật vendoring một cách rõ ràng, hãy gọi lệnh go với cờ -mod=vendor. Để tắt vendoring, hãy sử dụng cờ -mod=readonly hoặc -mod=mod.
Khi vendoring được bật, các lệnh build như go build và go test tải các gói từ thư mục vendor thay vì truy cập mạng hoặc bộ nhớ đệm module cục bộ. Lệnh go list -m chỉ in thông tin về các module được liệt kê trong go.mod. Các lệnh go mod như go mod download và go mod tidy không hoạt động khác đi khi vendoring được bật và vẫn sẽ tải xuống module cũng như truy cập bộ nhớ đệm module. go get cũng không hoạt động khác đi khi vendoring được bật.
Khác với vendoring trong chế độ GOPATH mode, lệnh go bỏ qua các thư mục vendor ở những vị trí khác ngoài thư mục gốc của module chính. Ngoài ra, vì các thư mục vendor trong các module khác không được sử dụng, lệnh go không đưa các thư mục vendor vào khi xây dựng tệp zip module (nhưng xem các lỗi đã biết #31562 và #37397).
go get
Cách dùng:
go get [-d] [-t] [-u] [-tool] [build flags] [packages]
Ví dụ:
# Nâng cấp một module cụ thể.
$ go get golang.org/x/net
# Nâng cấp các module cung cấp gói được nhập bởi các gói trong module chính.
$ go get -u ./...
# Nâng cấp hoặc hạ cấp xuống một phiên bản cụ thể của một module.
$ go get golang.org/x/text@v0.3.2
# Cập nhật đến commit trên nhánh master của module.
$ go get golang.org/x/text@master
# Xóa dependency đến một module và hạ cấp các module yêu cầu module đó
# xuống các phiên bản không yêu cầu module đó.
$ go get golang.org/x/text@none
# Nâng cấp phiên bản Go tối thiểu được yêu cầu cho module chính.
$ go get go
# Nâng cấp toolchain Go được đề xuất, giữ nguyên phiên bản Go tối thiểu.
$ go get toolchain
# Nâng cấp lên bản phát hành vá mới nhất của toolchain Go được đề xuất.
$ go get toolchain@patch
Lệnh go get cập nhật các dependency của module trong tệp go.mod của module chính, sau đó xây dựng và cài đặt các gói được liệt kê trên dòng lệnh.
Bước đầu tiên là xác định những module nào cần được cập nhật. go get nhận một danh sách các gói, mẫu gói và đường dẫn module làm đối số. Nếu một đối số gói được chỉ định, go get cập nhật module cung cấp gói đó. Nếu một mẫu gói được chỉ định (ví dụ: all hoặc một đường dẫn có ký tự đại diện ...), go get mở rộng mẫu thành một tập hợp các gói, sau đó cập nhật các module cung cấp các gói đó. Nếu một đối số đặt tên một module nhưng không phải một gói (ví dụ: module golang.org/x/net không có gói nào trong thư mục gốc), go get sẽ cập nhật module nhưng không xây dựng một gói. Nếu không có đối số nào được chỉ định, go get hoạt động như thể . đã được chỉ định (gói trong thư mục hiện tại); cách này có thể được dùng cùng cờ -u để cập nhật các module cung cấp các gói đã nhập.
Mỗi đối số có thể bao gồm một hậu tố truy vấn phiên bản cho biết phiên bản mong muốn, như trong go get golang.org/x/text@v0.3.0. Hậu tố truy vấn phiên bản bao gồm một ký hiệu @ theo sau bởi một truy vấn phiên bản, có thể chỉ định một phiên bản cụ thể (v0.3.0), tiền tố phiên bản (v0.3), tên nhánh hoặc thẻ (master), một bản sửa đổi (1234abcd), hoặc một trong các truy vấn đặc biệt latest, upgrade, patch hay none. Nếu không có phiên bản nào được cung cấp, go get sử dụng truy vấn @upgrade.
Sau khi go get đã phân giải các đối số của nó thành các module và phiên bản cụ thể, go get sẽ thêm, thay đổi hoặc xóa các chỉ thị require trong tệp go.mod của module chính để đảm bảo các module vẫn ở những phiên bản mong muốn trong tương lai. Lưu ý rằng các phiên bản được yêu cầu trong tệp go.mod là phiên bản tối thiểu và có thể được tự động tăng lên khi các dependency mới được thêm vào. Xem Lựa chọn phiên bản tối thiểu (MVS) để biết chi tiết về cách các phiên bản được lựa chọn và xung đột được giải quyết bởi các lệnh nhận biết module.
Các module khác có thể được nâng cấp khi một module được đặt tên trên dòng lệnh được thêm, nâng cấp hoặc hạ cấp nếu phiên bản mới của module được đặt tên yêu cầu các module khác ở phiên bản cao hơn. Ví dụ, giả sử module example.com/a được nâng cấp lên phiên bản v1.5.0, và phiên bản đó yêu cầu module example.com/b ở phiên bản v1.2.0. Nếu module example.com/b hiện được yêu cầu ở phiên bản v1.1.0, go get example.com/a@v1.5.0 cũng sẽ nâng cấp example.com/b lên v1.2.0.
Các module khác có thể bị hạ cấp khi một module được đặt tên trên dòng lệnh bị hạ cấp hoặc bị xóa. Tiếp tục ví dụ trên, giả sử module example.com/b bị hạ cấp xuống v1.1.0. Module example.com/a cũng sẽ bị hạ cấp xuống một phiên bản yêu cầu example.com/b ở phiên bản v1.1.0 hoặc thấp hơn.
Một yêu cầu module có thể được xóa bằng cách sử dụng hậu tố phiên bản @none. Đây là một dạng hạ cấp đặc biệt. Các module phụ thuộc vào module đã xóa sẽ bị hạ cấp hoặc xóa khi cần thiết. Một yêu cầu module có thể được xóa ngay cả khi một hoặc nhiều gói của nó được các gói trong module chính nhập. Trong trường hợp này, lệnh build tiếp theo có thể thêm một yêu cầu module mới.
Nếu một module cần thiết ở hai phiên bản khác nhau (được chỉ định rõ ràng trong các đối số dòng lệnh hoặc để đáp ứng việc nâng cấp và hạ cấp), go get sẽ báo lỗi.
Sau khi go get đã chọn một tập hợp phiên bản mới, nó kiểm tra xem bất kỳ phiên bản module mới được chọn nào hoặc bất kỳ module nào cung cấp các gói được đặt tên trên dòng lệnh có bị thu hồi hoặc bị phản đối hay không. go get in ra cảnh báo cho mỗi phiên bản bị thu hồi hoặc module bị phản đối mà nó tìm thấy. go list -m -u all có thể được sử dụng để kiểm tra việc thu hồi và phản đối trong tất cả dependency.
Sau khi go get cập nhật tệp go.mod, nó xây dựng các gói được đặt tên trên dòng lệnh. Các tệp thực thi sẽ được cài đặt trong thư mục được đặt tên bởi biến môi trường GOBIN, mặc định là $GOPATH/bin hoặc $HOME/go/bin nếu biến môi trường GOPATH chưa được thiết lập.
go get hỗ trợ các cờ sau:
- Cờ
-dchogo getbiết không xây dựng hoặc cài đặt các gói. Khi sử dụng-d,go getsẽ chỉ quản lý các dependency tronggo.mod. Việc sử dụnggo getkhông có-dđể xây dựng và cài đặt các gói đã bị phản đối (kể từ Go 1.17). Trong Go 1.18,-dsẽ luôn được bật. - Cờ
-uchogo getbiết nâng cấp các module cung cấp các gói được nhập trực tiếp hoặc gián tiếp bởi các gói được đặt tên trên dòng lệnh. Mỗi module được-uchọn sẽ được nâng cấp lên phiên bản mới nhất trừ khi nó đã được yêu cầu ở phiên bản cao hơn (một pre-release). - Cờ
-u=patch(không phải-u patch) cũng chogo getbiết nâng cấp các dependency, nhưnggo getsẽ nâng cấp từng dependency lên phiên bản patch mới nhất (tương tự truy vấn phiên bản@patch). - Cờ
-tchogo getbiết xem xét các module cần thiết để xây dựng bài kiểm thử của các gói được đặt tên trên dòng lệnh. Khi-tvà-uđược sử dụng cùng nhau,go getcũng sẽ cập nhật các dependency của bài kiểm thử. - Không nên sử dụng cờ
-insecurenữa. Cờ này cho phépgo getphân giải các đường dẫn import tùy chỉnh và lấy dữ liệu từ các repository cũng như proxy module bằng các lược đồ không an toàn như HTTP. Biến môi trườngGOINSECUREcung cấp khả năng kiểm soát chi tiết hơn và nên được sử dụng thay thế. - Cờ
-toolhướng dẫn go thêm một dòng tool tương ứng vàogo.modcho mỗi gói được liệt kê. Nếu-toolđược sử dụng với@none, dòng đó sẽ bị xóa.
Kể từ Go 1.16, go install là lệnh được khuyến nghị để xây dựng và cài đặt chương trình. Khi được sử dụng với hậu tố phiên bản (như @latest hoặc @v1.4.6), go install xây dựng các gói ở chế độ nhận biết module, bỏ qua tệp go.mod trong thư mục hiện tại hoặc bất kỳ thư mục cha nào nếu có.
go get tập trung hơn vào việc quản lý các yêu cầu trong go.mod. Cờ -d đã bị phản đối, và kể từ Go 1.18, cờ này luôn được bật.
go install
Cách dùng:
go install [build flags] [packages]
Ví dụ:
# Cài đặt phiên bản mới nhất của một chương trình,
# bỏ qua go.mod trong thư mục hiện tại (nếu có).
$ go install golang.org/x/tools/gopls@latest
# Cài đặt một phiên bản cụ thể của một chương trình.
$ go install golang.org/x/tools/gopls@v0.6.4
# Cài đặt một chương trình ở phiên bản được module trong thư mục hiện tại chọn.
$ go install golang.org/x/tools/gopls
# Cài đặt tất cả chương trình trong một thư mục.
$ go install ./cmd/...
Lệnh go install xây dựng và cài đặt các gói được đặt tên bởi các đường dẫn trên dòng lệnh. Các tệp thực thi (các gói main) được cài đặt vào thư mục được đặt tên bởi biến môi trường GOBIN, mặc định là $GOPATH/bin hoặc $HOME/go/bin nếu biến môi trường GOPATH chưa được đặt. Các tệp thực thi trong GOROOT được cài đặt vào $GOROOT/bin hoặc GOTOOLDIR thay vì GOBIN. Các gói không phải tệp thực thi được xây dựng và lưu vào bộ nhớ đệm nhưng không được cài đặt.
Kể từ Go 1.16, nếu các đối số có hậu tố phiên bản (như @latest hoặc @v1.0.0), go install xây dựng các gói ở chế độ nhận biết module, bỏ qua tệp go.mod trong thư mục hiện tại hoặc bất kỳ thư mục cha nào nếu có. Điều này hữu ích để cài đặt các tệp thực thi mà không ảnh hưởng đến các dependency của module chính.
Để loại bỏ sự mơ hồ về việc phiên bản module nào được sử dụng trong quá trình xây dựng, nếu bất kỳ đối số nào có hậu tố phiên bản, các đối số phải thỏa mãn các ràng buộc sau:
- Các đối số phải là đường dẫn gói hoặc mẫu gói (với ký tự đại diện “
...”). Chúng không được là các gói chuẩn (nhưfmt), các meta-pattern (std,cmd,all,work,tool), hoặc các đường dẫn tệp tương đối hay tuyệt đối. Lưu ý rằnggo install toolcó thể được sử dụng mà không có hậu tố phiên bản: xem bên dưới. - Tất cả đối số phải có cùng hậu tố phiên bản. Không cho phép các truy vấn khác nhau, ngay cả khi chúng tham chiếu đến cùng một phiên bản.
- Tất cả đối số phải tham chiếu đến các gói trong cùng một module ở cùng một phiên bản.
- Các đối số là đường dẫn gói phải tham chiếu đến các gói
main. Các đối số dạng mẫu chỉ khớp với các góimain. - Không có module nào được xem là module chính.
- Nếu module chứa các gói được đặt tên trên dòng lệnh có tệp
go.mod, tệp này không được chứa các chỉ thị (replacevàexclude) khiến nó được diễn giải khác đi nếu nó là module chính. - Module không được yêu cầu một phiên bản cao hơn của chính nó.
- Các thư mục vendor không được sử dụng trong bất kỳ module nào. (Các thư mục vendor không được bao gồm trong tệp zip module, vì vậy
go installkhông tải xuống chúng.)
- Nếu module chứa các gói được đặt tên trên dòng lệnh có tệp
Xem Truy vấn phiên bản để biết cú pháp truy vấn phiên bản được hỗ trợ. Go 1.15 trở xuống không hỗ trợ sử dụng truy vấn phiên bản với go install.
Nếu các đối số không có hậu tố phiên bản, go install có thể chạy ở chế độ nhận biết module hoặc chế độ GOPATH, tùy thuộc vào biến môi trường GO111MODULE và sự hiện diện của tệp go.mod. Xem các lệnh nhận biết module để biết chi tiết. Nếu chế độ nhận biết module được bật, go install chạy trong ngữ cảnh của module chính, có thể khác với module chứa gói đang được cài đặt. Ở chế độ nhận biết module, go install tool có thể được sử dụng từ một module để cài đặt tất cả tool trong module.
go tool
Cách dùng:
go tool [-n] command [args...]
Ví dụ:
$ go tool golang.org/x/tools/cmd/stringer
$ go tool stringer
Ở chế độ module, lệnh go tool có thể được dùng để xây dựng và chạy các công cụ được khai báo trong các tệp go.mod bằng chỉ thị tool.
Lệnh có thể được chỉ định bằng đường dẫn gói đầy đủ tới một công cụ được khai báo bằng chỉ thị tool. Tên binary mặc định của công cụ, là thành phần cuối cùng của đường dẫn gói, không bao gồm hậu tố phiên bản chính, cũng có thể được sử dụng nếu tên đó là duy nhất trong số các công cụ đã cài đặt.
go list -m
Cách dùng:
go list -m [-u] [-retracted] [-versions] [list flags] [modules]
Ví dụ:
$ go list -m all
$ go list -m -versions example.com/m
$ go list -m -json example.com/m@latest
Cờ -m khiến go list liệt kê các module thay vì các gói. Ở chế độ này, các đối số của go list có thể là module, mẫu module (chứa ký tự đại diện ...), truy vấn phiên bản, hoặc mẫu đặc biệt all, khớp với tất cả module trong danh sách build. Nếu không chỉ định đối số nào, module chính được liệt kê.
Khi liệt kê các module, cờ -f vẫn chỉ định một mẫu định dạng được áp dụng cho một cấu trúc Go, nhưng giờ đây là cấu trúc Module:
type Module struct {
Path string // đường dẫn module
Version string // phiên bản module
Versions []string // các phiên bản module có sẵn
Replace *Module // được thay thế bởi module này
Time *time.Time // thời điểm tạo phiên bản
Update *Module // bản cập nhật có sẵn (với -u)
Main bool // đây có phải là module chính không?
Indirect bool // module chỉ được module chính cần đến gián tiếp
Dir string // thư mục chứa bản sao cục bộ của tệp, nếu có
GoMod string // đường dẫn đến tệp go.mod mô tả module, nếu có
GoVersion string // phiên bản Go được dùng trong module
Retracted []string // thông tin thu hồi, nếu có (với -retracted hoặc -u)
Deprecated string // thông báo không còn được khuyến nghị, nếu có (với -u)
Error *ModuleError // lỗi khi tải module
}
type ModuleError struct {
Err string // chính lỗi đó
}
Đầu ra mặc định là in đường dẫn module rồi đến thông tin về phiên bản và việc thay thế nếu có. Ví dụ, go list -m all có thể in:
example.com/main/module
golang.org/x/net v0.1.0
golang.org/x/text v0.3.0 => /tmp/text
rsc.io/pdf v0.1.1
Cấu trúc Module có phương thức String định dạng dòng đầu ra này, vì vậy định dạng mặc định tương đương với -f '{{.String}}'.
Lưu ý rằng khi một module đã được thay thế, trường Replace của nó mô tả module thay thế, và trường Dir của nó được đặt thành mã nguồn của module thay thế nếu có. (Nghĩa là, nếu Replace khác nil, thì Dir được đặt thành Replace.Dir, không có quyền truy cập vào mã nguồn đã bị thay thế.)
Cờ -u thêm thông tin về các bản nâng cấp có sẵn. Khi phiên bản mới nhất của một module đã cho mới hơn phiên bản hiện tại, list -u đặt trường Update của module thành thông tin về module mới hơn. list -u cũng in liệu phiên bản hiện được chọn có bị thu hồi hay không và liệu module có không còn được khuyến nghị hay không. Phương thức String của module cho biết một bản nâng cấp có sẵn bằng cách định dạng phiên bản mới hơn trong dấu ngoặc vuông sau phiên bản hiện tại. Ví dụ, go list -m -u all có thể in:
example.com/main/module
golang.org/x/old v1.9.9 (deprecated)
golang.org/x/net v0.1.0 (retracted) [v0.2.0]
golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text
rsc.io/pdf v0.1.1 [v0.1.2]
(Đối với các công cụ, go list -m -u -json all có thể thuận tiện hơn để phân tích.)
Cờ -versions khiến list đặt trường Versions của module thành danh sách tất cả phiên bản đã biết của module đó, được sắp xếp theo quy tắc lập phiên bản ngữ nghĩa, từ thấp đến cao. Cờ này cũng thay đổi định dạng đầu ra mặc định để hiển thị đường dẫn module theo sau là danh sách phiên bản được phân tách bằng khoảng trắng. Các phiên bản bị thu hồi được loại khỏi danh sách này trừ khi cờ -retracted cũng được chỉ định.
Cờ -retracted yêu cầu list hiển thị các phiên bản bị thu hồi trong danh sách được in bằng cờ -versions và xem xét các phiên bản bị thu hồi khi phân giải truy vấn phiên bản. Ví dụ, go list -m -retracted example.com/m@latest hiển thị phiên bản bản phát hành hoặc pre-release cao nhất của module example.com/m, ngay cả khi phiên bản đó đã bị thu hồi.
Các chỉ thị retract và thông tin không còn được khuyến nghị được tải từ tệp go.mod ở phiên bản này. Cờ -retracted được thêm vào trong Go 1.16.
Hàm mẫu module nhận một đối số chuỗi duy nhất, đối số này phải là đường dẫn module hoặc truy vấn, và trả về module được chỉ định dưới dạng cấu trúc Module. Nếu xảy ra lỗi, kết quả sẽ là một cấu trúc Module có trường Error khác nil.
go mod download
Cách dùng:
go mod download [-x] [-json] [-reuse=old.json] [modules]
Ví dụ:
$ go mod download
$ go mod download golang.org/x/mod@v0.2.0
Lệnh go mod download tải các module được chỉ định vào bộ nhớ đệm module. Đối số có thể là đường dẫn module hoặc mẫu module chọn các dependency của module chính, hoặc truy vấn phiên bản có dạng path@version. Khi không có đối số, download áp dụng cho tất cả dependency của module chính.
Lệnh go sẽ tự động tải các module khi cần trong quá trình thực thi thông thường. Lệnh go mod download chủ yếu hữu ích để điền sẵn bộ nhớ đệm module hoặc để tải dữ liệu sẽ được cung cấp bởi module proxy.
Theo mặc định, download không ghi gì ra đầu ra tiêu chuẩn. Lệnh này in các thông báo tiến trình và lỗi ra luồng lỗi tiêu chuẩn.
Cờ -json khiến download in một chuỗi các đối tượng JSON ra đầu ra tiêu chuẩn, mô tả từng module đã tải xuống (hoặc lỗi), tương ứng với struct Go sau:
type Module struct {
Path string // đường dẫn module
Query string // truy vấn phiên bản tương ứng với phiên bản này
Version string // phiên bản module
Error string // lỗi khi tải module
Info string // đường dẫn tuyệt đối đến tệp .info đã lưu trong bộ nhớ đệm
GoMod string // đường dẫn tuyệt đối đến tệp .mod đã lưu trong bộ nhớ đệm
Zip string // đường dẫn tuyệt đối đến tệp .zip đã lưu trong bộ nhớ đệm
Dir string // đường dẫn tuyệt đối đến thư mục gốc mã nguồn đã lưu trong bộ nhớ đệm
Sum string // checksum cho đường dẫn, phiên bản (như trong go.sum)
GoModSum string // checksum cho go.mod (như trong go.sum)
Origin any // nguồn gốc của module
Reuse bool // việc tái sử dụng thông tin module cũ có an toàn hay không
}
Cờ -x khiến download in các lệnh mà download thực thi ra luồng lỗi tiêu chuẩn.
Cờ -reuse nhận tên của tệp chứa đầu ra JSON của một lần gọi ‘go mod download -json’ trước đó. Lệnh go có thể sử dụng tệp này để xác định rằng một module không thay đổi kể từ lần gọi trước đó và tránh tải lại module. Các module không được tải lại sẽ được đánh dấu trong đầu ra mới bằng cách đặt trường Reuse thành true. Thông thường bộ nhớ đệm module cung cấp kiểu tái sử dụng này một cách tự động; cờ -reuse có thể hữu ích trên các hệ thống không duy trì bộ nhớ đệm module.
go mod edit
Cách dùng:
go mod edit [editing flags] [-fmt|-print|-json] [go.mod]
Ví dụ:
# Thêm một chỉ thị replace.
$ go mod edit -replace example.com/a@v1.0.0=./a
# Xóa một chỉ thị replace.
$ go mod edit -dropreplace example.com/a@v1.0.0
# Đặt phiên bản go, thêm một yêu cầu, và in tệp
# thay vì ghi tệp vào đĩa.
$ go mod edit -go=1.14 -require=example.com/m@v1.0.0 -print
# Định dạng tệp go.mod.
$ go mod edit -fmt
# Định dạng và in một tệp .mod khác.
$ go mod edit -print tools.mod
# In biểu diễn JSON của tệp go.mod.
$ go mod edit -json
Lệnh go mod edit cung cấp một giao diện dòng lệnh để chỉnh sửa và định dạng các tệp go.mod, chủ yếu được sử dụng bởi các công cụ và script. go mod edit chỉ đọc một tệp go.mod; nó không tra cứu thông tin về các module khác. Theo mặc định, go mod edit đọc và ghi tệp go.mod của module chính, nhưng có thể chỉ định một tệp đích khác sau các cờ chỉnh sửa.
Các cờ chỉnh sửa chỉ định một chuỗi thao tác chỉnh sửa.
- Cờ
-modulethay đổi đường dẫn của module (dòng module trong tệpgo.mod). - Cờ
-go=versionđặt phiên bản ngôn ngữ Go được mong đợi. - Các cờ
-require=path@versionvà-droprequire=paththêm và xóa một yêu cầu đối với đường dẫn module và phiên bản đã cho. Lưu ý rằng-requireghi đè mọi yêu cầu hiện có trênpath. Các cờ này chủ yếu dành cho các công cụ hiểu đồ thị module. Người dùng nên ưu tiêngo get path@versionhoặcgo get path@none, vì các lệnh này thực hiện những điều chỉnhgo.modkhác khi cần để đáp ứng các ràng buộc do các module khác áp đặt. Xemgo get. - Các cờ
-exclude=path@versionvà-dropexclude=path@versionthêm và xóa một loại trừ đối với đường dẫn module và phiên bản đã cho. Lưu ý rằng-exclude=path@versionkhông thực hiện thao tác nào nếu loại trừ đó đã tồn tại. - Cờ
-replace=old[@v]=new[@v]thêm một thay thế cho cặp đường dẫn module và phiên bản đã cho. Nếu@vtrongold@vbị bỏ qua, một thay thế không có phiên bản ở phía bên trái sẽ được thêm vào, áp dụng cho mọi phiên bản của đường dẫn module cũ. Nếu@vtrongnew@vbị bỏ qua, đường dẫn mới phải là thư mục gốc của một module cục bộ, không phải là đường dẫn module. Lưu ý rằng-replaceghi đè mọi thay thế dư thừa choold[@v], vì vậy việc bỏ qua@vsẽ xóa các thay thế cho các phiên bản cụ thể. - Cờ
-dropreplace=old[@v]xóa một thay thế của cặp đường dẫn module và phiên bản đã cho. Nếu cung cấp@v, một thay thế với phiên bản đã cho sẽ bị xóa. Một thay thế hiện có không có phiên bản ở phía bên trái vẫn có thể thay thế module. Nếu bỏ qua@v, một thay thế không có phiên bản sẽ bị xóa. - Các cờ
-retract=versionvà-dropretract=versionthêm và xóa một khai báo thu hồi cho phiên bản đã cho, có thể là một phiên bản đơn (nhưv1.2.3) hoặc một khoảng (như[v1.1.0,v1.2.0]). Lưu ý rằng cờ-retractkhông thể thêm chú thích lý do cho chỉ thịretract. Các chú thích lý do được khuyến nghị và có thể được hiển thị bởigo list -m -uvà các lệnh khác. - Các cờ
-tool=pathvà-droptool=paththêm và xóa một chỉ thịtoolcho các đường dẫn đã cho. Lưu ý rằng thao tác này sẽ không thêm các dependency cần thiết vào đồ thị build. Người dùng nên ưu tiêngo get -tool pathđể thêm một công cụ, hoặcgo get -tool path@noneđể xóa một công cụ.
Các cờ chỉnh sửa có thể được lặp lại. Các thay đổi được áp dụng theo thứ tự đã cho.
go mod edit có thêm các cờ kiểm soát đầu ra của nó.
- Cờ
-fmtđịnh dạng lại tệpgo.modmà không thực hiện các thay đổi khác. Việc định dạng lại này cũng được ngầm thực hiện bởi bất kỳ sửa đổi nào khác sử dụng hoặc ghi lại tệpgo.mod. Chỉ cần dùng cờ này khi không chỉ định cờ nào khác, như tronggo mod edit -fmt. - Cờ
-printingo.modcuối cùng ở định dạng văn bản thay vì ghi lại vào đĩa. - Cờ
-jsoningo.modcuối cùng ở định dạng JSON thay vì ghi lại vào đĩa ở định dạng văn bản. Đầu ra JSON tương ứng với các kiểu Go sau:
type Module struct {
Path string
Version string
}
type GoMod struct {
Module ModPath
Go string
Require []Require
Exclude []Module
Replace []Replace
Retract []Retract
}
type ModPath struct {
Path string
Deprecated string
}
type Require struct {
Path string
Version string
Indirect bool
}
type Replace struct {
Old Module
New Module
}
type Retract struct {
Low string
High string
Rationale string
}
type Tool struct {
Path string
}
Lưu ý rằng điều này chỉ mô tả chính tệp go.mod, không phải các module khác được tham chiếu gián tiếp. Để có toàn bộ tập hợp module có sẵn cho một bản build, hãy dùng go list -m -json all. Xem go list -m.
Ví dụ, một công cụ có thể lấy tệp go.mod dưới dạng cấu trúc dữ liệu bằng cách phân tích đầu ra của go mod edit -json, sau đó có thể thực hiện thay đổi bằng cách gọi go mod edit với -require, -exclude, v.v.
Các công cụ cũng có thể sử dụng package golang.org/x/mod/modfile để phân tích cú pháp, chỉnh sửa và định dạng các tệp go.mod.
go mod graph
Cách dùng:
go mod graph [-go=version]
Lệnh go mod graph in đồ thị yêu cầu module (đã áp dụng các thay thế) dưới dạng văn bản. Ví dụ:
example.com/main example.com/a@v1.1.0
example.com/main example.com/b@v1.2.0
example.com/a@v1.1.0 example.com/b@v1.1.1
example.com/a@v1.1.0 example.com/c@v1.3.0
example.com/b@v1.1.0 example.com/c@v1.1.0
example.com/b@v1.2.0 example.com/c@v1.2.0
Mỗi đỉnh trong đồ thị module đại diện cho một phiên bản cụ thể của một module. Mỗi cạnh trong đồ thị đại diện cho một yêu cầu về phiên bản tối thiểu của một dependency.
go mod graph in các cạnh của đồ thị, mỗi cạnh trên một dòng. Mỗi dòng có hai trường được phân tách bằng khoảng trắng: một phiên bản module và một trong các dependency của nó. Mỗi phiên bản module được xác định dưới dạng chuỗi có dạng path@version. Module chính không có hậu tố @version, vì nó không có phiên bản.
Cờ -go khiến go mod graph báo cáo đồ thị module được tải bởi phiên bản Go đã cho, thay vì phiên bản được chỉ ra bởi chỉ thị go trong tệp go.mod.
Xem Lựa chọn phiên bản tối thiểu (MVS) để biết thêm thông tin về cách các phiên bản được chọn. Xem thêm go list -m để in các phiên bản đã chọn và go mod why để hiểu tại sao một module là cần thiết.
go mod init
Cách dùng:
go mod init [module-path]
Ví dụ:
go mod init
go mod init example.com/m
Lệnh go mod init khởi tạo và ghi một tệp go.mod mới trong thư mục hiện tại, về bản chất tạo một module mới có gốc tại thư mục hiện tại. Tệp go.mod không được tồn tại trước đó.
init chấp nhận một đối số tùy chọn, là đường dẫn module cho module mới. Xem Đường dẫn module để biết hướng dẫn về cách chọn đường dẫn module. Nếu đối số đường dẫn module bị bỏ qua, init sẽ cố gắng suy ra đường dẫn module bằng cách sử dụng các chú thích import trong các tệp .go và thư mục hiện tại (nếu nằm trong GOPATH).
go mod tidy
Cách dùng:
go mod tidy [-e] [-v] [-x] [-diff] [-go=version] [-compat=version]
go mod tidy đảm bảo tệp go.mod khớp với mã nguồn trong module. Lệnh này thêm mọi yêu cầu module còn thiếu cần thiết để xây dựng các gói và dependency của module hiện tại, đồng thời loại bỏ các yêu cầu đối với những module không cung cấp bất kỳ gói liên quan nào. Lệnh cũng thêm mọi mục còn thiếu vào go.sum và loại bỏ các mục không cần thiết.
Cờ -e (được thêm trong Go 1.16) khiến go mod tidy cố gắng tiếp tục thực hiện mặc dù gặp lỗi trong khi tải các gói.
Cờ -v khiến go mod tidy in thông tin về các module đã bị loại bỏ ra lỗi chuẩn.
Cờ -x khiến go mod tidy in các lệnh mà tidy thực thi.
Cờ -diff khiến go mod tidy không sửa đổi go.mod hoặc go.sum mà thay vào đó in các thay đổi cần thiết dưới dạng unified diff. Lệnh thoát với mã khác không nếu diff không rỗng.
go mod tidy hoạt động bằng cách tải tất cả các gói trong module chính, tất cả công cụ của module đó và tất cả các gói mà chúng import, theo cách đệ quy. Điều này bao gồm các gói được import bởi các bài kiểm thử (bao gồm cả các bài kiểm thử trong những module khác). go mod tidy hoạt động như thể tất cả build tag đều được bật, vì vậy nó sẽ xem xét các tệp mã nguồn dành riêng cho nền tảng và các tệp yêu cầu build tag tùy chỉnh, ngay cả khi những tệp mã nguồn đó thường không được xây dựng. Có một ngoại lệ: build tag ignore không được bật, vì vậy tệp có ràng buộc build // +build ignore sẽ không được xem xét. Lưu ý rằng go mod tidy sẽ không xem xét các gói trong module chính nằm trong các thư mục có tên testdata hoặc có tên bắt đầu bằng . hay _, trừ khi các gói đó được các gói khác import một cách rõ ràng.
Sau khi go mod tidy đã tải tập hợp các gói này, nó đảm bảo rằng mỗi module cung cấp một hoặc nhiều gói có một chỉ thị require trong tệp go.mod của module chính hoặc — nếu module chính ở phiên bản go 1.16 trở xuống — được một module được yêu cầu khác yêu cầu. go mod tidy sẽ thêm yêu cầu đối với phiên bản mới nhất của mỗi module còn thiếu (xem Truy vấn phiên bản để biết định nghĩa của phiên bản latest). go mod tidy sẽ loại bỏ các chỉ thị require đối với những module không cung cấp bất kỳ gói nào trong tập hợp được mô tả ở trên.
go mod tidy cũng có thể thêm hoặc xóa các chú thích // indirect trên các chỉ thị require. Một chú thích // indirect biểu thị một module không cung cấp gói được import bởi một gói trong module chính. (Xem chỉ thị require để biết thêm chi tiết về thời điểm các dependency và chú thích // indirect được thêm vào.)
Nếu cờ -go được đặt, go mod tidy sẽ cập nhật chỉ thị go thành phiên bản được chỉ định, bật hoặc tắt cắt tỉa đồ thị module và tải module lười (đồng thời thêm hoặc xóa các yêu cầu gián tiếp khi cần) theo phiên bản đó.
Theo mặc định, go mod tidy sẽ kiểm tra rằng các phiên bản được chọn của các module không thay đổi khi đồ thị module được tải bởi phiên bản Go ngay trước phiên bản được chỉ định trong chỉ thị go. Phiên bản được kiểm tra để tương thích cũng có thể được chỉ định rõ ràng thông qua cờ -compat.
go mod vendor
Cách dùng:
go mod vendor [-e] [-v] [-o]
Lệnh go mod vendor tạo một thư mục có tên vendor trong thư mục gốc của module chính, chứa các bản sao của tất cả gói cần thiết để hỗ trợ việc xây dựng và kiểm thử các gói trong module chính. Các gói chỉ được nhập bởi các bài kiểm thử của những gói bên ngoài module chính sẽ không được đưa vào. Tương tự như go mod tidy và các lệnh module khác, ràng buộc xây dựng ngoại trừ ignore không được xem xét khi tạo thư mục vendor.
Khi vendoring được bật, lệnh go sẽ tải các gói từ thư mục vendor thay vì tải xuống các module từ nguồn của chúng vào bộ nhớ đệm module và sử dụng các gói từ những bản sao đã tải xuống đó. Xem Vendoring để biết thêm thông tin.
go mod vendor cũng tạo tệp vendor/modules.txt, chứa danh sách các gói đã được vendoring và các phiên bản module mà chúng được sao chép từ đó. Khi vendoring được bật, tệp kê khai này được dùng làm nguồn thông tin về phiên bản module, như được báo cáo bởi go list -m và go version -m. Khi lệnh go đọc vendor/modules.txt, nó kiểm tra rằng các phiên bản module nhất quán với go.mod. Nếu go.mod đã thay đổi kể từ khi vendor/modules.txt được tạo, cần chạy lại go mod vendor.
Lưu ý rằng go mod vendor xóa thư mục vendor nếu thư mục này tồn tại trước khi tạo lại nó. Không nên thực hiện các thay đổi cục bộ đối với các gói đã được vendoring. Lệnh go không kiểm tra rằng các gói trong thư mục vendor có bị sửa đổi hay không, nhưng bạn có thể xác minh tính toàn vẹn của thư mục vendor bằng cách chạy go mod vendor và kiểm tra rằng không có thay đổi nào được thực hiện.
Cờ -e (được thêm trong Go 1.16) khiến go mod vendor cố gắng tiếp tục thực hiện bất chấp các lỗi gặp phải khi tải các gói.
Cờ -v khiến go mod vendor in tên của các module và gói đã được vendoring ra lỗi chuẩn.
Cờ -o (được thêm trong Go 1.18) khiến go mod vendor xuất cây vendor tại thư mục được chỉ định thay vì vendor. Đối số có thể là một đường dẫn tuyệt đối hoặc một đường dẫn tương đối so với thư mục gốc của module.
go mod verify
Cách dùng:
go mod verify
go mod verify kiểm tra rằng các dependency của module chính được lưu trữ trong module cache chưa bị sửa đổi kể từ khi chúng được tải xuống. Để thực hiện việc kiểm tra này, go mod verify băm từng tệp .zip module đã tải xuống và thư mục đã giải nén, sau đó so sánh các giá trị băm đó với một giá trị băm được ghi lại khi module được tải xuống lần đầu. go mod verify kiểm tra từng module trong danh sách build (có thể được in bằng go list -m all).
Nếu tất cả module không bị sửa đổi, go mod verify in ra “all modules verified”. Nếu không, lệnh báo cáo những module đã bị thay đổi và thoát với trạng thái khác không.
Lưu ý rằng tất cả lệnh nhận biết module đều xác minh rằng các giá trị băm trong tệp go.sum của module chính khớp với các giá trị băm được ghi lại cho các module đã tải xuống vào module cache. Nếu thiếu một giá trị băm trong go.sum (ví dụ vì module đang được sử dụng lần đầu), lệnh go sẽ xác minh giá trị băm của nó bằng cơ sở dữ liệu checksum (trừ khi đường dẫn module khớp với GOPRIVATE hoặc GONOSUMDB). Xem Xác thực module để biết chi tiết.
Ngược lại, go mod verify kiểm tra rằng các tệp .zip của module và các thư mục đã giải nén của chúng có giá trị băm khớp với các giá trị băm được ghi lại trong module cache khi chúng được tải xuống lần đầu. Điều này hữu ích để phát hiện các thay đổi đối với tệp trong module cache sau khi một module đã được tải xuống và xác minh. go mod verify không tải xuống nội dung cho các module không có trong cache và không sử dụng các tệp go.sum để xác minh nội dung module. Tuy nhiên, go mod verify có thể tải xuống các tệp go.mod để thực hiện lựa chọn phiên bản tối thiểu. Nó sẽ sử dụng go.sum để xác minh các tệp đó và có thể thêm các mục go.sum cho những giá trị băm bị thiếu.
go mod why
Cách dùng:
go mod why [-m] [-vendor] packages...
go mod why hiển thị đường dẫn ngắn nhất trong đồ thị import từ module chính đến từng gói được liệt kê.
Đầu ra là một chuỗi các đoạn, mỗi đoạn dành cho một gói hoặc module được đặt tên trên dòng lệnh, được phân tách bằng các dòng trống. Mỗi đoạn bắt đầu bằng một dòng chú thích bắt đầu bằng # cho biết gói hoặc module đích. Các dòng tiếp theo cung cấp một đường dẫn qua đồ thị import, mỗi dòng một gói. Nếu gói hoặc module không được tham chiếu từ module chính, đoạn đó sẽ hiển thị một ghi chú duy nhất trong dấu ngoặc đơn cho biết điều đó.
Ví dụ:
$ go mod why golang.org/x/text/language golang.org/x/text/encoding
# golang.org/x/text/language
rsc.io/quote
rsc.io/sampler
golang.org/x/text/language
# golang.org/x/text/encoding
(main module does not need package golang.org/x/text/encoding)
Cờ -m khiến go mod why xử lý các đối số của nó như một danh sách module. go mod why sẽ in một đường dẫn đến bất kỳ gói nào trong mỗi module. Lưu ý rằng ngay cả khi sử dụng -m, go mod why truy vấn đồ thị gói, không phải đồ thị module được in bởi go mod graph.
Cờ -vendor khiến go mod why bỏ qua các import trong các bài kiểm tra của những gói bên ngoài module chính (như go mod vendor thực hiện). Theo mặc định, go mod why xem xét đồ thị của các gói được khớp bởi mẫu all. Cờ này không có tác dụng sau Go 1.16 trong các module khai báo go 1.16 trở lên (sử dụng chỉ thị go trong go.mod), vì ý nghĩa của all đã thay đổi để khớp với tập hợp các gói được khớp bởi go mod vendor.
go version -m
Cách dùng:
go version [-m] [-v] [file ...]
Ví dụ:
# In phiên bản Go được dùng để xây dựng go.
$ go version
# In phiên bản Go được dùng để xây dựng một tệp thực thi cụ thể.
$ go version ~/go/bin/gopls
# In phiên bản Go và các phiên bản module được dùng để xây dựng một tệp thực thi cụ thể.
$ go version -m ~/go/bin/gopls
# In phiên bản Go và các phiên bản module được dùng để xây dựng các tệp thực thi trong một thư mục.
$ go version -m ~/go/bin/
go version báo cáo phiên bản Go được dùng để xây dựng từng tệp thực thi có tên trên dòng lệnh.
Nếu không có tệp nào được đặt tên trên dòng lệnh, go version in thông tin phiên bản của chính nó.
Nếu một thư mục được đặt tên, go version duyệt đệ quy qua thư mục đó, tìm các binary Go được nhận dạng và báo cáo phiên bản của chúng. Theo mặc định, go version không báo cáo các tệp không được nhận dạng được tìm thấy trong quá trình quét thư mục. Cờ -v khiến nó báo cáo các tệp không được nhận dạng.
Cờ -m khiến go version in thông tin phiên bản module được nhúng của mỗi tệp thực thi, khi có sẵn. Với mỗi tệp thực thi, go version -m in một bảng có các cột được phân tách bằng tab như bảng dưới đây.
$ go version -m ~/go/bin/goimports
/home/jrgopher/go/bin/goimports: go1.14.3
path golang.org/x/tools/cmd/goimports
mod golang.org/x/tools v0.0.0-20200518203908-8018eb2c26ba h1:0Lcy64USfQQL6GAJma8BdHCgeofcchQj+Z7j0SXYAzU=
dep golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
dep golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
Định dạng của bảng có thể thay đổi trong tương lai. Có thể lấy được cùng thông tin từ
runtime/debug.ReadBuildInfo.
Ý nghĩa của mỗi hàng trong bảng được xác định bởi từ trong cột đầu tiên.
path: đường dẫn của góimainđược dùng để xây dựng tệp thực thi.mod: module chứa góimain. Các cột lần lượt là đường dẫn module, phiên bản và tổng kiểm tra. module chính có phiên bản(devel)và không có tổng kiểm tra.dep: một module cung cấp một hoặc nhiều gói được liên kết vào tệp thực thi. Cùng định dạng vớimod.=>: một thay thế cho module ở dòng trước đó. Nếu thay thế là một thư mục cục bộ, chỉ có đường dẫn thư mục được liệt kê (không có phiên bản hoặc tổng kiểm tra). Nếu thay thế là một phiên bản module, đường dẫn, phiên bản và tổng kiểm tra được liệt kê, giống như vớimodvàdep. Một module được thay thế không có tổng kiểm tra.
go clean -modcache
Cách dùng:
go clean [-modcache]
Cờ -modcache khiến go clean xóa toàn bộ bộ nhớ đệm mô-đun, bao gồm mã nguồn chưa giải nén của các dependency có phiên bản.
Đây thường là cách tốt nhất để xóa bộ nhớ đệm mô-đun. Theo mặc định, hầu hết tệp và thư mục trong bộ nhớ đệm mô-đun là chỉ đọc để ngăn các bài kiểm thử và trình soạn thảo vô tình thay đổi tệp sau khi chúng đã được xác thực. Tuy nhiên, điều này khiến các lệnh như rm -r thất bại, vì không thể xóa tệp nếu chưa làm cho các thư mục cha của chúng có quyền ghi.
Cờ -modcacherw (được chấp nhận bởi go build và các lệnh khác có hỗ trợ mô-đun) khiến các thư mục mới trong bộ nhớ đệm mô-đun có quyền ghi. Để truyền -modcacherw cho tất cả các lệnh có hỗ trợ mô-đun, hãy thêm cờ này vào biến GOFLAGS. GOFLAGS có thể được đặt trong môi trường hoặc bằng go env -w. Ví dụ, lệnh dưới đây đặt giá trị này vĩnh viễn:
go env -w GOFLAGS=-modcacherw
Nên sử dụng -modcacherw một cách thận trọng; các nhà phát triển nên cẩn thận không thực hiện thay đổi đối với các tệp trong bộ nhớ đệm mô-đun. Có thể dùng go mod verify để kiểm tra rằng các tệp trong bộ nhớ đệm khớp với các hash trong tệp go.sum của mô-đun chính.
Truy vấn phiên bản
Một số lệnh cho phép bạn chỉ định phiên bản của một mô-đun bằng cách sử dụng truy vấn phiên bản, xuất hiện sau ký tự @ theo sau đường dẫn mô-đun hoặc gói trên dòng lệnh.
Ví dụ:
go get example.com/m@latest
go mod download example.com/m@master
go list -m -json example.com/m@e3702bed2
Một truy vấn phiên bản có thể là một trong các dạng sau:
- Một phiên bản semantic đầy đủ, chẳng hạn như
v1.2.3, chọn một phiên bản cụ thể. Xem Các phiên bản để biết cú pháp. - Một tiền tố phiên bản semantic, chẳng hạn như
v1hoặcv1.2, chọn phiên bản cao nhất hiện có với tiền tố đó. - Một phép so sánh phiên bản semantic, chẳng hạn như
<v1.2.3or>=v1.5.6, chọn phiên bản hiện có gần nhất với mục tiêu so sánh (phiên bản thấp nhất cho>và>=, và phiên bản cao nhất cho<and<=). - Một mã định danh bản sửa đổi cho repository nguồn bên dưới, chẳng hạn như tiền tố hash commit, thẻ bản sửa đổi hoặc tên nhánh. Nếu bản sửa đổi được gắn thẻ bằng một phiên bản semantic, truy vấn này chọn phiên bản đó. Nếu không, truy vấn này chọn một pseudo-version cho commit bên dưới. Lưu ý rằng các nhánh và thẻ có tên khớp với các truy vấn phiên bản khác không thể được chọn theo cách này. Ví dụ, truy vấn
v2chọn phiên bản mới nhất bắt đầu bằngv2, không phải nhánh có tênv2. - Chuỗi
latest, chọn bản phát hành có phiên bản cao nhất hiện có. Nếu không có phiên bản bản phát hành,latestchọn phiên bản pre-release cao nhất. Nếu không có phiên bản được gắn thẻ,latestchọn một pseudo-version cho commit tại đầu nhánh mặc định của repository. - Chuỗi
upgrade, tương tự nhưlatestngoại trừ việc nếu mô-đun hiện đang được yêu cầu ở phiên bản cao hơn phiên bản màlatestsẽ chọn (ví dụ: một pre-release),upgradesẽ chọn phiên bản hiện tại. - Chuỗi
patch, chọn phiên bản hiện có mới nhất có cùng số phiên bản chính và phụ với phiên bản hiện đang được yêu cầu. Nếu hiện không có phiên bản nào được yêu cầu,patchtương đương vớilatest. Kể từ Go 1.16,go getyêu cầu có phiên bản hiện tại khi sử dụngpatch(nhưng cờ-u=patchkhông có yêu cầu này).
Ngoại trừ các truy vấn cho phiên bản hoặc bản sửa đổi được đặt tên cụ thể, tất cả truy vấn đều xem xét các phiên bản hiện có được báo cáo bởi go list -m -versions (xem go list -m). Danh sách này chỉ chứa các phiên bản được gắn thẻ, không chứa pseudo-version. Các phiên bản mô-đun bị loại trừ bởi chỉ thị exclude trong tệp go.mod của mô-đun chính sẽ không được xem xét. Các phiên bản được bao phủ bởi chỉ thị retract trong tệp go.mod từ phiên bản latest của cùng mô-đun cũng bị bỏ qua, ngoại trừ khi cờ -retracted được sử dụng với go list -m và ngoại trừ khi tải các chỉ thị retract.
Các phiên bản bản phát hành được ưu tiên hơn các phiên bản pre-release. Ví dụ: nếu có các phiên bản v1.2.2 và v1.2.3-pre, truy vấn latest sẽ chọn v1.2.2, dù v1.2.3-pre cao hơn. Truy vấn <v1.2.4 cũng sẽ chọn v1.2.2, dù v1.2.3-pre gần với v1.2.4 hơn. Nếu không có phiên bản bản phát hành hoặc pre-release nào, các truy vấn latest, upgrade và patch sẽ chọn một pseudo-version cho commit tại đầu nhánh mặc định của repository. Các truy vấn khác sẽ báo lỗi.
Lệnh module bên ngoài một module
Các lệnh Go nhận biết module thường chạy trong ngữ cảnh của module chính được xác định bởi tệp go.mod trong thư mục làm việc hoặc thư mục cha. Một số lệnh có thể được chạy ở chế độ nhận biết module mà không cần tệp go.mod, nhưng hầu hết lệnh hoạt động khác đi hoặc báo lỗi khi không có tệp go.mod.
Xem các lệnh nhận biết module để biết thông tin về việc bật và tắt chế độ nhận biết module.
| Lệnh | Hành vi |
|---|---|
go buildgo docgo fixgo fmtgo generatego installgo listgo rungo testgo vet
|
Chỉ các gói trong thư viện chuẩn và các gói được chỉ định dưới dạng tệp
.go trên dòng lệnh mới có thể được tải, nhập và xây dựng.
Không thể xây dựng các gói từ những module khác, vì không có nơi để ghi
lại các yêu cầu module và đảm bảo các bản dựng xác định.
|
go get |
Các gói và tệp thực thi có thể được xây dựng và cài đặt như bình thường.
Lưu ý rằng không có module chính khi go get được chạy mà
không có tệp go.mod, vì vậy các chỉ thị replace
và exclude không được áp dụng.
|
go list -m |
Cần có truy vấn phiên bản rõ ràng cho
hầu hết đối số, ngoại trừ khi cờ -versions được sử dụng.
|
go mod download |
Cần có truy vấn phiên bản rõ ràng cho hầu hết đối số. |
go mod edit |
Cần có đối số tệp rõ ràng. |
go mod graphgo mod tidygo mod vendorgo mod verifygo mod why
|
Các lệnh này yêu cầu tệp go.mod và sẽ báo lỗi nếu tệp đó
không tồn tại.
|
go work init
Cách dùng:
go work init [moddirs]
Init khởi tạo và ghi một tệp go.work mới trong thư mục hiện tại, về cơ bản tạo một workspace mới tại thư mục hiện tại.
go work init tùy chọn chấp nhận các đường dẫn đến các module trong workspace làm đối số. Nếu bỏ qua đối số, một workspace trống không có module nào sẽ được tạo.
Mỗi đường dẫn đối số được thêm vào một chỉ thị use trong tệp go.work. Phiên bản Go hiện tại cũng sẽ được liệt kê trong tệp go.work.
go work edit
Cách dùng:
go work edit [editing flags] [go.work]
Lệnh go work edit cung cấp giao diện dòng lệnh để chỉnh sửa go.work,
chủ yếu được dùng bởi các công cụ hoặc script. Lệnh này chỉ đọc go.work;
nó không tra cứu thông tin về các module liên quan.
Nếu không chỉ định tệp, Edit sẽ tìm tệp go.work trong thư mục hiện tại
và các thư mục cha của nó
Các cờ chỉnh sửa chỉ định một chuỗi thao tác chỉnh sửa.
- Cờ
-fmtđịnh dạng lại tệp go.work mà không thực hiện các thay đổi khác. Việc định dạng lại này cũng được ngầm thực hiện bởi bất kỳ sửa đổi nào khác sử dụng hoặc ghi lại tệpgo.work. Cờ này chỉ cần thiết khi không có cờ nào khác được chỉ định, như trong ‘go work edit-fmt’. - Các cờ
-use=pathvà-dropuse=paththêm và xóa một chỉ thị use khỏi tập hợp thư mục module của tệpgo.work. - Cờ
-replace=old[@v]=new[@v]thêm một thay thế cho cặp đường dẫn module và phiên bản đã cho. Nếu@vtrongold@vbị bỏ qua, một thay thế không có phiên bản ở phía bên trái sẽ được thêm vào, áp dụng cho tất cả phiên bản của đường dẫn module cũ. Nếu@vtrongnew@vbị bỏ qua, đường dẫn mới phải là một thư mục gốc module cục bộ, không phải đường dẫn module. Lưu ý rằng-replaceghi đè mọi thay thế dư thừa choold[@v], vì vậy việc bỏ qua@vsẽ xóa các thay thế hiện có cho các phiên bản cụ thể. - Cờ
-dropreplace=old[@v]xóa một thay thế của cặp đường dẫn module và phiên bản đã cho. Nếu bỏ qua@v, một thay thế không có phiên bản ở phía bên trái sẽ bị xóa. - Cờ
-go=versionđặt phiên bản ngôn ngữ Go mong muốn.
Các cờ chỉnh sửa có thể được lặp lại. Các thay đổi được áp dụng theo thứ tự đã cho.
go work edit có thêm các cờ kiểm soát đầu ra của nó
- Cờ -print in go.work cuối cùng ở định dạng văn bản thay vì ghi ngược lại vào go.mod.
- Cờ -json in tệp go.work cuối cùng ở định dạng JSON thay vì ghi ngược lại vào go.mod. Đầu ra JSON tương ứng với các kiểu Go sau:
type Module struct {
Path string
Version string
}
type GoWork struct {
Go string
Directory []Directory
Replace []Replace
}
type Use struct {
Path string
ModulePath string
}
type Replace struct {
Old Module
New Module
}
go work use
Cách dùng:
go work use [-r] [moddirs]
Lệnh go work use cung cấp giao diện dòng lệnh để thêm các thư mục, tùy chọn đệ quy, vào tệp go.work.
Một chỉ thị use sẽ được thêm vào tệp go.work cho mỗi thư mục đối số được liệt kê trên dòng lệnh của tệp go.work, nếu thư mục đó tồn tại trên đĩa, hoặc bị xóa khỏi tệp go.work nếu thư mục đó không tồn tại trên đĩa.
Cờ -r tìm kiếm đệ quy các module trong các thư mục đối số, và lệnh use hoạt động như thể mỗi thư mục đó được chỉ định làm đối số.
go work sync
Cách dùng:
go work sync
Lệnh go work sync đồng bộ danh sách build của workspace trở lại các module của workspace.
Danh sách build của workspace là tập hợp các phiên bản của tất cả các module dependency (bắc cầu) được sử dụng để thực hiện build trong workspace. go work sync tạo danh sách build đó bằng cách sử dụng thuật toán Lựa chọn phiên bản tối thiểu (MVS), sau đó đồng bộ các phiên bản đó trở lại từng module được chỉ định trong workspace (bằng các chỉ thị use).
Sau khi danh sách build của workspace được tính toán, tệp go.mod của từng module trong workspace được viết lại với các dependency liên quan đến module đó được nâng cấp để khớp với danh sách build của workspace.
Lưu ý rằng Lựa chọn phiên bản tối thiểu đảm bảo rằng phiên bản của mỗi module trong danh sách build luôn bằng hoặc cao hơn phiên bản đó trong từng module của workspace.
Proxy module
Giao thức GOPROXY
Một proxy module là một máy chủ HTTP có thể phản hồi các yêu cầu GET cho những đường dẫn được chỉ định bên dưới. Các yêu cầu không có tham số truy vấn và không yêu cầu tiêu đề cụ thể, vì vậy ngay cả một trang phục vụ từ hệ thống tệp cố định (bao gồm URL file://) cũng có thể là một proxy module.
Các phản hồi HTTP thành công phải có mã trạng thái 200 (OK). Các chuyển hướng (3xx) được thực hiện theo. Các phản hồi có mã trạng thái 4xx và 5xx được xem là lỗi. Các mã lỗi 404 (Not Found) và 410 (Gone) cho biết module hoặc phiên bản được yêu cầu không có trên proxy, nhưng có thể được tìm thấy ở nơi khác. Các phản hồi lỗi nên có kiểu nội dung text/plain với charset là utf-8 hoặc us-ascii.
Lệnh go có thể được cấu hình để liên hệ với các proxy hoặc máy chủ quản lý mã nguồn bằng biến môi trường GOPROXY, biến này nhận một danh sách URL proxy. Danh sách này có thể bao gồm các từ khóa direct hoặc off (xem Biến môi trường để biết chi tiết). Các phần tử trong danh sách có thể được phân tách bằng dấu phẩy (,) hoặc dấu gạch đứng (|), các dấu này quyết định hành vi dự phòng khi lỗi. Khi một URL theo sau bởi dấu phẩy, lệnh go chỉ chuyển sang các nguồn sau khi nhận phản hồi 404 (Not Found) hoặc 410 (Gone). Khi một URL theo sau bởi dấu gạch đứng, lệnh go chuyển sang các nguồn sau sau bất kỳ lỗi nào, bao gồm cả các lỗi không phải HTTP như hết thời gian chờ. Hành vi xử lý lỗi này cho phép proxy hoạt động như một cổng kiểm soát đối với các module chưa biết. Ví dụ, một proxy có thể phản hồi lỗi 403 (Forbidden) cho các module không nằm trong danh sách được phê duyệt (xem Proxy riêng tư phục vụ các module riêng tư).
Bảng bên dưới chỉ định các truy vấn mà một proxy module phải phản hồi. Với mỗi đường dẫn, $base là phần đường dẫn của URL proxy, $module là đường dẫn module, và $version là một phiên bản. Ví dụ, nếu URL proxy là https://example.com/mod, và máy khách đang yêu cầu tệp go.mod cho module golang.org/x/text ở phiên bản v0.3.2, máy khách sẽ gửi một yêu cầu GET cho https://example.com/mod/golang.org/x/text/@v/v0.3.2.mod.
Để tránh sự không rõ ràng khi phục vụ từ các hệ thống tệp không phân biệt chữ hoa chữ thường, các phần tử $module và $version được mã hóa chữ hoa chữ thường bằng cách thay thế mỗi chữ cái viết hoa bằng một dấu chấm than theo sau bởi chữ cái viết thường tương ứng. Điều này cho phép các module example.com/M và example.com/m đều được lưu trữ trên đĩa, vì module trước được mã hóa thành example.com/!m.
| Đường dẫn | Mô tả |
|---|---|
$base/$module/@v/list |
Trả về danh sách các phiên bản đã biết của module đã cho dưới dạng văn bản thuần, mỗi phiên bản trên một dòng. Danh sách này không nên bao gồm các pseudo-version. |
$base/$module/@v/$version.info |
Trả về metadata được định dạng JSON về một phiên bản cụ thể của một module. Phản hồi phải là một đối tượng JSON tương ứng với cấu trúc dữ liệu Go bên dưới:
type Info struct {
Version string // chuỗi phiên bản
Time time.Time // thời gian commit
}
Trường
Trường Các trường khác có thể được thêm vào trong tương lai, vì vậy các tên khác được dành riêng. |
$base/$module/@v/$version.mod |
Trả về tệp go.mod cho một phiên bản cụ thể của một module.
Nếu module không có tệp go.mod ở phiên bản được yêu cầu,
phải trả về một tệp chỉ chứa câu lệnh module với đường dẫn
module được yêu cầu. Nếu không, phải trả về tệp go.mod
nguyên bản, chưa được sửa đổi.
|
$base/$module/@v/$version.zip |
Trả về một tệp zip chứa nội dung của một phiên bản cụ thể của một module. Xem Các tệp zip của module để biết chi tiết về cách định dạng tệp zip này. |
$base/$module/@latest |
Trả về metadata được định dạng JSON về phiên bản mới nhất đã biết của
một module theo cùng định dạng với
$base/$module/@v/$version.info. Phiên bản mới nhất nên là
phiên bản của module mà lệnh go nên sử dụng nếu
$base/$module/@v/list trống hoặc không có phiên bản nào
được liệt kê phù hợp. Endpoint này là tùy chọn và các proxy module
không bắt buộc phải triển khai nó.
|
Khi xác định phiên bản mới nhất của một module, lệnh go sẽ yêu cầu
$base/$module/@v/list, sau đó, nếu không tìm thấy phiên bản phù hợp,
$base/$module/@latest. Lệnh go ưu tiên theo thứ tự: phiên bản bản phát hành
cao nhất về mặt ngữ nghĩa, phiên bản pre-release cao nhất về mặt ngữ nghĩa và
pseudo-version gần đây nhất theo thời gian. Trong Go 1.12 trở về trước, lệnh
go xem các pseudo-version trong $base/$module/@v/list là các phiên bản
pre-release, nhưng điều này không còn đúng kể từ Go 1.13.
Một module proxy phải luôn cung cấp cùng một nội dung cho các phản hồi thành công
đối với các truy vấn $base/$module/$version.mod và $base/$module/$version.zip.
Nội dung này được xác thực bằng mật mã bằng cách sử dụng các
tệp go.sum và theo mặc định là cơ sở dữ liệu checksum.
Lệnh go lưu vào bộ nhớ đệm hầu hết nội dung mà nó tải xuống từ các module proxy
trong bộ nhớ đệm module tại $GOPATH/pkg/mod/cache/download. Ngay cả khi tải
trực tiếp từ các hệ thống quản lý phiên bản, lệnh go tạo ra các tệp info,
mod và zip rõ ràng rồi lưu chúng trong thư mục này, giống như khi nó tải
chúng trực tiếp từ một proxy. Bố cục bộ nhớ đệm giống với không gian URL của
proxy, vì vậy việc cung cấp $GOPATH/pkg/mod/cache/download tại (hoặc sao chép
nó tới) https://example.com/proxy sẽ cho phép
người dùng truy cập các phiên bản module đã lưu trong bộ nhớ đệm bằng cách đặt
GOPROXY thành https://example.com/proxy.
Giao tiếp với các proxy
Lệnh go có thể tải mã nguồn module và metadata từ một module proxy. Biến môi trường GOPROXY có thể được dùng để cấu hình các proxy mà lệnh go có thể kết nối tới và liệu lệnh có thể giao tiếp trực tiếp với hệ thống quản lý phiên bản hay không. Dữ liệu module đã tải xuống được lưu trong bộ nhớ đệm module. Lệnh go chỉ liên hệ với một proxy khi cần thông tin chưa có trong bộ nhớ đệm.
Phần giao thức GOPROXY mô tả các yêu cầu có thể được gửi tới máy chủ GOPROXY. Tuy nhiên, cũng hữu ích khi hiểu thời điểm lệnh go thực hiện các yêu cầu này. Ví dụ, go build thực hiện theo quy trình dưới đây:
- Tính toán danh sách build bằng cách đọc các tệp
go.modvà thực hiện lựa chọn phiên bản tối thiểu (MVS). - Đọc các gói được đặt tên trên dòng lệnh và các gói mà chúng import.
- Nếu một gói không được cung cấp bởi bất kỳ module nào trong danh sách build, tìm một module cung cấp gói đó. Thêm yêu cầu module với phiên bản mới nhất của nó vào
go.mod, rồi bắt đầu lại. - Build các gói sau khi mọi thứ đã được tải.
Khi lệnh go tính toán danh sách build, nó tải tệp go.mod cho mỗi module trong đồ thị module. Nếu tệp go.mod không có trong bộ nhớ đệm, lệnh go sẽ tải nó từ proxy bằng yêu cầu $module/@v/$version.mod (trong đó $module là đường dẫn module và $version là phiên bản). Các yêu cầu này có thể được kiểm thử bằng một công cụ như curl. Ví dụ, lệnh dưới đây tải tệp go.mod cho golang.org/x/mod tại phiên bản v0.2.0:
$ curl https://proxy.golang.org/golang.org/x/mod/@v/v0.2.0.mod
module golang.org/x/mod
go 1.12
require (
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898
)
Để tải một gói, lệnh go cần mã nguồn của module cung cấp gói đó. Mã nguồn module được phân phối trong các tệp .zip, sau đó được giải nén vào bộ nhớ đệm module. Nếu tệp .zip của một module không có trong bộ nhớ đệm, lệnh go sẽ tải nó bằng yêu cầu $module/@v/$version.zip.
$ curl -O https://proxy.golang.org/golang.org/x/mod/@v/v0.2.0.zip
$ unzip -l v0.2.0.zip | head
Archive: v0.2.0.zip
Length Date Time Name
--------- ---------- ----- ----
1479 00-00-1980 00:00 golang.org/x/mod@v0.2.0/LICENSE
1303 00-00-1980 00:00 golang.org/x/mod@v0.2.0/PATENTS
559 00-00-1980 00:00 golang.org/x/mod@v0.2.0/README
21 00-00-1980 00:00 golang.org/x/mod@v0.2.0/codereview.cfg
214 00-00-1980 00:00 golang.org/x/mod@v0.2.0/go.mod
1476 00-00-1980 00:00 golang.org/x/mod@v0.2.0/go.sum
5224 00-00-1980 00:00 golang.org/x/mod@v0.2.0/gosumcheck/main.go
Lưu ý rằng các yêu cầu .mod và .zip là riêng biệt, mặc dù các tệp go.mod thường nằm trong các tệp .zip. Lệnh go có thể cần tải các tệp go.mod cho nhiều module khác nhau, và các tệp .mod nhỏ hơn nhiều so với các tệp .zip. Ngoài ra, nếu một dự án Go không có tệp go.mod, proxy sẽ phục vụ một tệp go.mod tổng hợp chỉ chứa một chỉ thị module. Các tệp go.mod tổng hợp được lệnh go tạo ra khi tải xuống từ một hệ thống quản lý phiên bản.
Nếu lệnh go cần tải một gói không được cung cấp bởi bất kỳ module nào trong danh sách build, nó sẽ cố gắng tìm một module mới cung cấp gói đó. Phần Giải quyết một gói thành một module mô tả quy trình này. Tóm lại, lệnh go yêu cầu thông tin về phiên bản mới nhất của từng đường dẫn module có khả năng chứa gói đó. Ví dụ, với gói golang.org/x/net/html, lệnh go sẽ thử tìm các phiên bản mới nhất của các module golang.org/x/net/html, golang.org/x/net, golang.org/x/, và golang.org. Chỉ golang.org/x/net thực sự tồn tại và cung cấp gói đó, vì vậy lệnh go sử dụng phiên bản mới nhất của module đó. Nếu có nhiều hơn một module cung cấp gói, lệnh go sẽ sử dụng module có đường dẫn dài nhất.
Khi lệnh go yêu cầu phiên bản mới nhất của một module, trước tiên nó gửi yêu cầu cho $module/@v/list. Nếu danh sách trống hoặc không có phiên bản nào được trả về có thể sử dụng, nó gửi yêu cầu cho $module/@latest. Sau khi chọn được một phiên bản, lệnh go gửi yêu cầu $module/@v/$version.info để lấy metadata. Sau đó, nó có thể gửi các yêu cầu $module/@v/$version.mod và $module/@v/$version.zip để tải tệp go.mod và mã nguồn.
$ curl https://proxy.golang.org/golang.org/x/mod/@v/list
v0.1.0
v0.2.0
$ curl https://proxy.golang.org/golang.org/x/mod/@v/v0.2.0.info
{"Version":"v0.2.0","Time":"2020-01-02T17:33:45Z"}
Sau khi tải tệp .mod hoặc .zip, lệnh go tính toán một hàm băm mật mã và kiểm tra rằng nó khớp với một hàm băm trong tệp go.sum của module chính. Nếu hàm băm không có trong go.sum, theo mặc định, lệnh go sẽ lấy nó từ cơ sở dữ liệu checksum. Nếu hàm băm được tính toán không khớp, lệnh go báo cáo lỗi bảo mật và không cài đặt tệp vào bộ nhớ đệm module. Các biến môi trường GOPRIVATE và GONOSUMDB có thể được dùng để vô hiệu hóa các yêu cầu tới cơ sở dữ liệu checksum cho các module cụ thể. Biến môi trường GOSUMDB cũng có thể được đặt thành off để vô hiệu hóa hoàn toàn các yêu cầu tới cơ sở dữ liệu checksum. Xem Xác thực module để biết thêm thông tin. Lưu ý rằng danh sách phiên bản và metadata phiên bản được trả về cho các yêu cầu .info không được xác thực và có thể thay đổi theo thời gian.
Cung cấp module trực tiếp từ một proxy
Hầu hết module được phát triển và cung cấp từ một kho lưu trữ kiểm soát phiên bản. Ở
chế độ trực tiếp, lệnh go tải xuống một module như vậy bằng
một công cụ kiểm soát phiên bản (xem Hệ thống kiểm soát phiên bản). Cũng có thể
cung cấp một module trực tiếp từ một module proxy. Điều này hữu ích cho các tổ chức
muốn cung cấp module mà không để lộ các máy chủ kiểm soát phiên bản của họ và
cho các tổ chức sử dụng các công cụ kiểm soát phiên bản mà lệnh go không
hỗ trợ.
Khi lệnh go tải xuống một module ở chế độ trực tiếp, trước tiên nó tra cứu URL
của máy chủ module bằng một yêu cầu HTTP GET dựa trên đường dẫn module. Nó tìm
một thẻ <meta> có tên go-import trong phản hồi HTML. Nội dung của thẻ phải
chứa đường dẫn gốc của kho lưu trữ, hệ thống kiểm soát
phiên bản và URL, được phân tách bằng dấu cách. Xem Tìm kho lưu trữ cho một đường
dẫn module để biết chi tiết.
Nếu hệ thống kiểm soát phiên bản là mod, lệnh go tải xuống module từ URL đã
cho bằng cách sử dụng giao thức GOPROXY.
Ví dụ, giả sử lệnh go đang cố tải xuống module
example.com/gopher tại phiên bản v1.0.0. Nó gửi một yêu cầu tới
https://example.com/gopher?go-get=1. Máy chủ phản hồi bằng một tài liệu HTML
chứa thẻ:
<meta name="go-import" content="example.com/gopher mod https://modproxy.example.com">
Dựa trên phản hồi này, lệnh go tải xuống module bằng cách gửi các yêu cầu tới
https://modproxy.example.com/example.com/gopher/@v/v1.0.0.info,
v1.0.0.mod và v1.0.0.zip.
Lưu ý rằng các module được cung cấp trực tiếp từ một proxy không thể được tải
xuống bằng go get ở chế độ GOPATH.
Hệ thống kiểm soát phiên bản
Lệnh go có thể tải xuống mã nguồn module và siêu dữ liệu trực tiếp từ một
kho lưu trữ kiểm soát phiên bản. Việc tải xuống một module từ một
proxy thường nhanh hơn, nhưng kết nối trực tiếp
tới một kho lưu trữ là cần thiết nếu không có proxy hoặc nếu kho lưu trữ của một
module không thể được proxy truy cập (thường đúng với các kho lưu trữ riêng tư).
Git, Subversion, Mercurial, Bazaar và Fossil được hỗ trợ. Một công cụ kiểm soát
phiên bản phải được cài đặt trong một thư mục thuộc PATH để lệnh
go có thể sử dụng nó.
Để tải xuống các module cụ thể từ các kho lưu trữ mã nguồn thay vì một proxy, hãy đặt
các biến môi trường GOPRIVATE hoặc GONOPROXY. Để cấu hình lệnh go
tải xuống trực tiếp tất cả module từ các kho lưu trữ mã nguồn, hãy đặt GOPROXY
thành direct. Xem Các biến môi trường để biết thêm
thông tin.
Tìm kho lưu trữ cho đường dẫn mô-đun
Khi lệnh go tải xuống một mô-đun ở chế độ direct, trước tiên nó bắt đầu bằng việc xác định kho lưu trữ chứa mô-đun đó.
Nếu đường dẫn mô-đun có bộ định danh VCS (một trong .bzr, .fossil, .git, .hg, .svn) ở cuối một thành phần đường dẫn, lệnh go sẽ sử dụng mọi thứ trước bộ định danh đường dẫn đó làm URL của kho lưu trữ. Ví dụ, với mô-đun example.com/foo.git/bar, lệnh go tải xuống kho lưu trữ tại example.com/foo bằng git, và mong đợi tìm thấy mô-đun trong thư mục con bar. Lệnh go sẽ đoán giao thức cần dùng dựa trên các giao thức được công cụ quản lý phiên bản hỗ trợ.
Nếu đường dẫn mô-đun không có bộ định danh, lệnh go gửi một yêu cầu HTTP GET đến URL được tạo từ đường dẫn mô-đun với chuỗi truy vấn ?go-get=1. Ví dụ, với mô-đun golang.org/x/mod, lệnh go có thể gửi các yêu cầu sau:
https://golang.org/x/mod?go-get=1 (preferred)
http://golang.org/x/mod?go-get=1 (fallback, only with GOINSECURE)
Lệnh go theo dõi các chuyển hướng nhưng bỏ qua mã trạng thái phản hồi, vì vậy máy chủ có thể phản hồi bằng 404 hoặc bất kỳ trạng thái lỗi nào khác. Biến môi trường GOINSECURE có thể được đặt để cho phép dự phòng và chuyển hướng sang HTTP không mã hóa cho các mô-đun cụ thể.
Máy chủ phải phản hồi bằng một tài liệu HTML chứa thẻ <meta> trong phần <head> của tài liệu. Thẻ <meta> nên xuất hiện sớm trong tài liệu để tránh gây nhầm lẫn cho bộ phân tích cú pháp bị giới hạn của lệnh go. Cụ thể, thẻ này nên xuất hiện trước mọi JavaScript hoặc CSS thô. Thẻ <meta> phải có dạng:
<meta name="go-import" content="root-path vcs repo-url [subdirectory]">
root-path là đường dẫn gốc của kho lưu trữ, phần của đường dẫn mô-đun tương ứng với thư mục gốc của kho lưu trữ, hoặc với subdirectory nếu có và sử dụng Go 1.25 trở lên (xem phần về subdirectory bên dưới). Nó phải là tiền tố hoặc khớp chính xác với đường dẫn mô-đun được yêu cầu. Nếu không khớp chính xác, một yêu cầu khác sẽ được thực hiện cho tiền tố đó để xác minh các thẻ <meta> khớp nhau.
vcs là hệ thống quản lý phiên bản. Nó phải là một trong các công cụ được liệt kê trong bảng bên dưới hoặc từ khóa mod, chỉ thị cho lệnh go tải mô-đun từ URL đã cho bằng giao thức GOPROXY. Xem Phục vụ mô-đun trực tiếp từ proxy để biết chi tiết.
repo-url là URL của kho lưu trữ, chứa một lược đồ và không chứa bộ định danh .vcs. Các giao thức không an toàn (như http:// và git://) chỉ có thể được sử dụng nếu đường dẫn mô-đun được khớp bởi biến môi trường GOINSECURE.
subdirectory, nếu có, là thư mục con được phân tách bằng dấu gạch chéo của kho lưu trữ mà root-path tương ứng, ghi đè lên mặc định là thư mục gốc của kho lưu trữ. Các thẻ meta go-import cung cấp subdirectory chỉ được Go 1.25 trở lên nhận dạng. Các lần thử tải xuống để phân giải mô-đun trên các phiên bản Go cũ hơn sẽ bỏ qua thẻ meta và dẫn đến lỗi phân giải nếu mô-đun không thể được phân giải ở nơi khác.
| Name | Command | GOVCS default | Secure schemes |
|---|---|---|---|
| Bazaar | bzr |
Private only | https, bzr+ssh |
| Fossil | fossil |
Private only | https |
| Git | git |
Public and private | https, git+ssh, ssh |
| Mercurial | hg |
Public and private | https, ssh |
| Subversion | svn |
Private only | https, svn+ssh |
Ví dụ, hãy xem lại golang.org/x/mod. Lệnh go gửi một yêu cầu đến https://golang.org/x/mod?go-get=1. Máy chủ phản hồi bằng một tài liệu HTML chứa thẻ:
<meta name="go-import" content="golang.org/x/mod git https://go.googlesource.com/mod">
Từ phản hồi này, lệnh go sẽ sử dụng kho lưu trữ Git tại URL từ xa https://go.googlesource.com/mod.
GitHub và các dịch vụ lưu trữ phổ biến khác phản hồi các truy vấn ?go-get=1 cho tất cả kho lưu trữ, vì vậy thông thường không cần cấu hình máy chủ cho các mô-đun được lưu trữ trên những trang đó.
Sau khi tìm thấy URL của kho lưu trữ, lệnh go sẽ sao chép kho lưu trữ vào bộ nhớ đệm mô-đun. Nhìn chung, lệnh go cố gắng tránh lấy dữ liệu không cần thiết từ một kho lưu trữ. Tuy nhiên, các lệnh thực tế được sử dụng thay đổi theo hệ thống quản lý phiên bản và có thể thay đổi theo thời gian. Với Git, lệnh go có thể liệt kê hầu hết các phiên bản có sẵn mà không cần tải xuống các commit. Nó thường sẽ lấy các commit mà không tải xuống các commit tổ tiên, nhưng đôi khi việc đó là cần thiết.
Ánh xạ phiên bản tới các commit
Lệnh go có thể checkout một module trong một kho lưu trữ tại một phiên bản chuẩn cụ thể như v1.2.3, v2.4.0-beta hoặc v3.0.0+incompatible. Mỗi phiên bản module nên có một thẻ phiên bản ngữ nghĩa trong kho lưu trữ, cho biết revision nào cần được checkout cho một phiên bản nhất định.
Nếu một module được định nghĩa trong thư mục gốc của kho lưu trữ hoặc trong một thư mục con phiên bản major của thư mục gốc, thì tên của mỗi thẻ phiên bản bằng với phiên bản tương ứng. Ví dụ, module golang.org/x/text được định nghĩa trong thư mục gốc của kho lưu trữ, vì vậy phiên bản v0.3.2 có thẻ v0.3.2 trong kho lưu trữ đó. Điều này đúng với hầu hết các module.
Nếu một module được định nghĩa trong một thư mục con bên trong kho lưu trữ, tức là phần thư mục con của module trong đường dẫn module không rỗng, thì mỗi tên thẻ phải được thêm tiền tố là thư mục con của module, theo sau bởi dấu gạch chéo. Ví dụ, module golang.org/x/tools/gopls được định nghĩa trong thư mục con gopls của kho lưu trữ có đường dẫn gốc golang.org/x/tools. Phiên bản v0.4.0 của module đó phải có thẻ có tên gopls/v0.4.0 trong kho lưu trữ đó.
Số phiên bản major của một thẻ phiên bản ngữ nghĩa phải nhất quán với hậu tố phiên bản major của đường dẫn module (nếu có). Ví dụ, thẻ v1.0.0 có thể thuộc về module example.com/mod nhưng không thể thuộc về example.com/mod/v2, vì module đó sẽ có các thẻ như v2.0.0.
Một thẻ có phiên bản major v2 trở lên có thể thuộc về một module không có hậu tố phiên bản major nếu không có tệp go.mod và module nằm trong thư mục gốc của kho lưu trữ. Loại phiên bản này được biểu thị bằng hậu tố +incompatible. Bản thân thẻ phiên bản không được có hậu tố này. Xem Tính tương thích với các kho lưu trữ không phải module.
Sau khi một thẻ được tạo, không nên xóa hoặc thay đổi nó sang một revision khác. Các phiên bản được xác thực để đảm bảo các bản build an toàn và có thể lặp lại. Nếu một thẻ bị thay đổi, client có thể gặp lỗi bảo mật khi tải xuống thẻ đó. Ngay cả sau khi một thẻ bị xóa, nội dung của nó vẫn có thể còn khả dụng trên các module proxy.
Ánh xạ pseudo-version tới commit
Lệnh go có thể kiểm tra một module trong một repository tại một revision cụ thể, được mã hóa dưới dạng pseudo-version như
v1.3.2-0.20191109021931-daa7c04131f5.
12 ký tự cuối của pseudo-version (daa7c04131f5 trong ví dụ trên) chỉ ra một revision trong repository cần được kiểm tra. Ý nghĩa của phần này phụ thuộc vào hệ thống quản lý phiên bản. Với Git và Mercurial, đây là tiền tố của một commit hash. Với Subversion, đây là một số revision được đệm bằng số 0.
Trước khi kiểm tra một commit, lệnh go xác minh rằng dấu thời gian (20191109021931 ở trên) khớp với ngày của commit. Lệnh cũng xác minh rằng phiên bản cơ sở (v1.3.1, phiên bản trước v1.3.2 trong ví dụ trên) tương ứng với một thẻ phiên bản semantic là tổ tiên của commit. Các kiểm tra này đảm bảo rằng tác giả module có toàn quyền kiểm soát cách các pseudo-version được so sánh với các phiên bản đã phát hành khác.
Xem Pseudo-versions để biết thêm thông tin.
Ánh xạ branch và commit tới phiên bản
Một module có thể được kiểm tra tại một branch, tag hoặc revision cụ thể bằng cách sử dụng truy vấn phiên bản.
go get example.com/mod@master
Lệnh go chuyển đổi các tên này thành phiên bản chuẩn có thể được sử dụng với lựa chọn phiên bản tối thiểu (MVS). MVS phụ thuộc vào khả năng sắp xếp các phiên bản một cách không mơ hồ. Tên branch và revision không thể được so sánh đáng tin cậy theo thời gian, vì chúng phụ thuộc vào cấu trúc repository, vốn có thể thay đổi.
Nếu một revision được gắn một hoặc nhiều tag phiên bản semantic như v1.2.3, tag cho phiên bản hợp lệ cao nhất sẽ được sử dụng. Lệnh go chỉ xem xét các tag phiên bản semantic có thể thuộc về module đích; ví dụ, tag v1.5.2 sẽ không được xem xét cho example.com/mod/v2 vì phiên bản chính không khớp với hậu tố của đường dẫn module.
Nếu một revision không được gắn tag phiên bản semantic hợp lệ, lệnh go sẽ tạo một pseudo-version. Nếu revision có các tổ tiên với tag phiên bản semantic hợp lệ, phiên bản tổ tiên cao nhất sẽ được sử dụng làm cơ sở của pseudo-version. Xem Pseudo-versions.
Thư mục module trong một kho lưu trữ
Sau khi kho lưu trữ của một module đã được checkout tại một revision cụ thể, lệnh go phải tìm thư mục chứa tệp go.mod của module (thư mục gốc của module).
Hãy nhớ rằng đường dẫn module bao gồm ba phần: đường dẫn gốc của kho lưu trữ (tương ứng với thư mục gốc của kho lưu trữ), một thư mục con của module và hậu tố phiên bản chính (chỉ dành cho các module được bản phát hành tại v2 trở lên).
Với hầu hết module, đường dẫn module bằng với đường dẫn gốc của kho lưu trữ, vì vậy thư mục gốc của module là thư mục gốc của kho lưu trữ.
Các module đôi khi được định nghĩa trong các thư mục con của kho lưu trữ. Điều này thường được thực hiện cho các kho lưu trữ lớn có nhiều thành phần cần được bản phát hành và tạo phiên bản độc lập. Một module như vậy được kỳ vọng nằm trong một thư mục con khớp với phần trong đường dẫn module sau đường dẫn gốc của kho lưu trữ. Ví dụ: giả sử module example.com/monorepo/foo/bar nằm trong kho lưu trữ có đường dẫn gốc example.com/monorepo. Tệp go.mod của nó phải nằm trong thư mục con foo/bar.
Nếu một module được bản phát hành tại phiên bản chính v2 trở lên, đường dẫn của nó phải có hậu tố phiên bản chính. Một module có hậu tố phiên bản chính có thể được định nghĩa trong một trong hai thư mục con: một thư mục có hậu tố và một thư mục không có hậu tố. Ví dụ: giả sử một phiên bản mới của module ở trên được bản phát hành với đường dẫn example.com/monorepo/foo/bar/v2. Tệp go.mod của nó có thể nằm trong foo/bar hoặc foo/bar/v2.
Các thư mục con có hậu tố phiên bản chính là thư mục con phiên bản chính. Chúng có thể được dùng để phát triển nhiều phiên bản chính của một module trên cùng một branch. Điều này có thể không cần thiết khi việc phát triển nhiều phiên bản chính diễn ra trên các branch riêng biệt. Tuy nhiên, các thư mục con phiên bản chính có một thuộc tính quan trọng: trong chế độ GOPATH, đường dẫn import gói khớp chính xác với các thư mục bên dưới GOPATH/src. Lệnh go cung cấp khả năng tương thích module tối thiểu trong chế độ GOPATH (xem Khả năng tương thích với các kho lưu trữ không phải module), vì vậy các thư mục con phiên bản chính không phải lúc nào cũng cần thiết để tương thích với các dự án được xây dựng trong chế độ GOPATH. Tuy nhiên, các công cụ cũ không hỗ trợ khả năng tương thích module tối thiểu có thể gặp vấn đề.
Sau khi lệnh go tìm thấy thư mục gốc của module, nó tạo một tệp .zip chứa nội dung của thư mục, sau đó giải nén tệp .zip vào bộ đệm module. Xem các ràng buộc về đường dẫn và kích thước tệp để biết chi tiết về các tệp có thể được đưa vào tệp .zip. Nội dung của tệp .zip được xác thực trước khi giải nén vào bộ đệm module theo cùng cách như khi tệp .zip được tải xuống từ một proxy.
Các tệp zip của module không bao gồm nội dung của các thư mục vendor hoặc bất kỳ module lồng nhau nào (các thư mục con chứa tệp go.mod). Điều này có nghĩa là một module phải cẩn thận không tham chiếu đến các tệp bên ngoài thư mục của nó hoặc trong các module khác. Ví dụ: các mẫu //go:embed không được khớp với các tệp trong các module lồng nhau. Hành vi này có thể là một giải pháp thay thế hữu ích trong các trường hợp không nên đưa tệp vào một module. Ví dụ: nếu một kho lưu trữ có các tệp lớn được đưa vào thư mục testdata, tác giả module có thể thêm một tệp go.mod rỗng vào testdata để người dùng của họ không cần tải xuống các tệp đó. Tất nhiên, điều này có thể làm giảm độ phủ đối với người dùng đang kiểm thử các dependency của họ.
Trường hợp đặc biệt đối với tệp LICENSE
Khi lệnh go tạo tệp .zip cho một mô-đun không nằm trong thư mục gốc của kho lưu trữ, nếu mô-đun không có tệp có tên LICENSE trong thư mục gốc của nó (cùng với go.mod), lệnh go sẽ sao chép tệp có tên LICENSE từ thư mục gốc của kho lưu trữ nếu tệp đó có trong cùng một bản sửa đổi.
Trường hợp đặc biệt này cho phép cùng một tệp LICENSE được áp dụng cho tất cả các mô-đun trong một kho lưu trữ. Điều này chỉ áp dụng cho các tệp có tên chính xác là LICENSE, không có phần mở rộng như .txt. Đáng tiếc, điều này không thể được mở rộng mà không làm hỏng các tổng kiểm tra mật mã của các mô-đun hiện có; xem Xác thực mô-đun. Các công cụ và trang web khác như pkg.go.dev có thể nhận ra các tệp có tên khác.
Cũng lưu ý rằng lệnh go không bao gồm các liên kết tượng trưng khi tạo tệp .zip của mô-đun; xem Các ràng buộc về đường dẫn và kích thước tệp. Do đó, nếu một kho lưu trữ không có tệp LICENSE trong thư mục gốc, các tác giả có thể thay vào đó tạo các bản sao của tệp giấy phép trong các mô-đun được định nghĩa trong thư mục con để đảm bảo các tệp đó được đưa vào tệp .zip của mô-đun.
Kiểm soát các công cụ quản lý phiên bản bằng GOVCS
Khả năng tải xuống mô-đun bằng các lệnh quản lý phiên bản như git của lệnh go rất quan trọng đối với hệ sinh thái gói phi tập trung, trong đó mã có thể được nhập từ bất kỳ máy chủ nào. Khả năng này cũng là một vấn đề bảo mật tiềm ẩn nếu một máy chủ độc hại tìm ra cách khiến lệnh quản lý phiên bản được gọi chạy mã không mong muốn.
Để cân bằng các mối quan tâm về chức năng và bảo mật, theo mặc định lệnh go chỉ sử dụng git và hg để tải xuống mã từ các máy chủ công khai. Nó sẽ sử dụng bất kỳ hệ thống quản lý phiên bản đã biết nào để tải xuống mã từ các máy chủ riêng tư, được định nghĩa là những máy chủ lưu trữ các gói khớp với biến môi trường GOPRIVATE. Lý do chỉ cho phép Git và Mercurial là vì hai hệ thống này đã nhận được nhiều sự chú ý nhất về các vấn đề khi được chạy với vai trò máy khách của các máy chủ không đáng tin cậy. Ngược lại, Bazaar, Fossil và Subversion chủ yếu được sử dụng trong các môi trường đáng tin cậy, đã được xác thực và không được xem xét kỹ lưỡng về các bề mặt tấn công như vậy.
Các hạn chế đối với lệnh quản lý phiên bản chỉ áp dụng khi sử dụng quyền truy cập quản lý phiên bản trực tiếp để tải xuống mã. Khi tải xuống mô-đun từ proxy, lệnh go sử dụng giao thức GOPROXY thay thế, giao thức này luôn được cho phép. Theo mặc định, lệnh go sử dụng máy nhân bản mô-đun Go (proxy.golang.org) cho các mô-đun công khai và chỉ chuyển sang quản lý phiên bản đối với các mô-đun riêng tư hoặc khi máy nhân bản từ chối phục vụ một gói công khai (thường vì lý do pháp lý). Do đó, theo mặc định, người dùng vẫn có thể truy cập mã công khai được phục vụ từ các kho lưu trữ Bazaar, Fossil hoặc Subversion, vì các lượt tải xuống đó sử dụng máy nhân bản mô-đun Go, nơi chịu rủi ro bảo mật khi chạy các lệnh quản lý phiên bản bằng một hộp cát tùy chỉnh.
Biến GOVCS có thể được sử dụng để thay đổi các hệ thống quản lý phiên bản được phép cho các mô-đun cụ thể. Biến GOVCS áp dụng khi xây dựng các gói ở cả chế độ nhận biết mô-đun và chế độ GOPATH. Khi sử dụng mô-đun, các mẫu được so khớp với đường dẫn mô-đun. Khi sử dụng GOPATH, các mẫu được so khớp với đường dẫn nhập tương ứng với gốc của kho lưu trữ quản lý phiên bản.
Dạng tổng quát của biến GOVCS là danh sách các quy tắc pattern:vcslist được phân tách bằng dấu phẩy. Mẫu là một mẫu glob phải khớp với một hoặc nhiều phần tử đầu tiên của đường dẫn mô-đun hoặc đường dẫn nhập. vcslist là danh sách các lệnh quản lý phiên bản được phép được phân tách bằng dấu gạch đứng, hoặc all để cho phép sử dụng bất kỳ lệnh nào đã biết, hoặc off để không cho phép gì cả. Lưu ý rằng nếu một mô-đun khớp với một mẫu có vcslist off, mô-đun đó vẫn có thể được tải xuống nếu máy chủ gốc sử dụng lược đồ mod, lược đồ này hướng dẫn lệnh go tải xuống mô-đun bằng giao thức GOPROXY. Mẫu khớp sớm nhất trong danh sách sẽ được áp dụng, ngay cả khi các mẫu sau cũng có thể khớp.
Ví dụ, hãy xem xét:
GOVCS=github.com:git,evil.com:off,*:git|hg
Với thiết lập này, mã có mô-đun hoặc đường dẫn nhập bắt đầu bằng github.com/ chỉ có thể sử dụng git; các đường dẫn trên evil.com không thể sử dụng bất kỳ lệnh quản lý phiên bản nào, và tất cả các đường dẫn khác (* khớp với mọi thứ) chỉ có thể sử dụng git hoặc hg.
Các mẫu đặc biệt public và private khớp với các đường dẫn mô-đun hoặc đường dẫn nhập công khai và riêng tư. Một đường dẫn là riêng tư nếu nó khớp với biến GOPPRIVATE; nếu không thì nó là công khai.
Nếu không có quy tắc nào trong biến GOVCS khớp với một mô-đun hoặc đường dẫn nhập cụ thể, lệnh go áp dụng quy tắc mặc định của nó, hiện có thể được tóm tắt bằng ký hiệu GOVCS là public:git|hg,private:all.
Để cho phép sử dụng không hạn chế bất kỳ hệ thống quản lý phiên bản nào cho bất kỳ gói nào, hãy dùng:
GOVCS=*:all
Để vô hiệu hóa toàn bộ việc sử dụng quản lý phiên bản, hãy dùng:
GOVCS=*:off
Có thể sử dụng lệnh go env -w command để đặt biến GOVCS cho các lần gọi lệnh go trong tương lai.
GOVCS được giới thiệu trong Go 1.16. Các phiên bản Go trước đó có thể sử dụng bất kỳ công cụ quản lý phiên bản nào đã biết cho bất kỳ mô-đun nào.
Tệp zip của mô-đun
Các phiên bản mô-đun được phân phối dưới dạng tệp .zip. Hiếm khi cần tương tác trực tiếp với các tệp này, vì lệnh go tự động tạo, tải xuống và giải nén chúng từ module proxies và các repository kiểm soát phiên bản. Tuy nhiên, việc hiểu về các tệp này vẫn hữu ích để nắm được các ràng buộc tương thích đa nền tảng hoặc khi triển khai một module proxy.
Lệnh go mod download tải xuống các tệp zip cho một hoặc nhiều mô-đun, sau đó giải nén các tệp đó vào bộ nhớ đệm mô-đun. Tùy thuộc vào GOPROXY và các biến môi trường khác, lệnh go có thể tải các tệp zip từ một proxy hoặc sao chép các repository mã nguồn và tạo tệp zip từ chúng. Cờ -json có thể được dùng để tìm vị trí của các tệp zip đã tải xuống và nội dung đã giải nén của chúng trong bộ nhớ đệm mô-đun.
Gói golang.org/x/mod/zip có thể được dùng để tạo, giải nén hoặc kiểm tra nội dung của các tệp zip theo chương trình.
Ràng buộc về đường dẫn tệp và kích thước
Có một số hạn chế đối với nội dung của các tệp zip mô-đun. Những ràng buộc này đảm bảo rằng các tệp zip có thể được giải nén an toàn và nhất quán trên nhiều nền tảng.
- Một tệp zip mô-đun có thể có kích thước tối đa 500 MiB. Tổng kích thước chưa nén của các tệp trong đó cũng bị giới hạn ở mức 500 MiB. Các tệp
go.modbị giới hạn ở 16 MiB. Các tệpLICENSEcũng bị giới hạn ở 16 MiB. Những giới hạn này tồn tại để giảm thiểu các cuộc tấn công từ chối dịch vụ nhắm vào người dùng, proxy và các phần khác của hệ sinh thái mô-đun. Các repository chứa hơn 500 MiB tệp trong cây thư mục mô-đun nên gắn thẻ các phiên bản mô-đun tại các commit chỉ bao gồm những tệp cần thiết để xây dựng các gói của mô-đun; video, mô hình và các tài sản lớn khác thường không cần thiết cho việc xây dựng. - Mỗi tệp trong một tệp zip mô-đun phải bắt đầu bằng tiền tố
$module@$version/trong đó$modulelà đường dẫn mô-đun và$versionlà phiên bản, ví dụ,golang.org/x/mod@v0.3.0/. Đường dẫn mô-đun phải hợp lệ, phiên bản phải hợp lệ và chuẩn, đồng thời phiên bản phải khớp với hậu tố phiên bản chính của đường dẫn mô-đun. Xem Đường dẫn và phiên bản mô-đun để biết các định nghĩa và hạn chế cụ thể. - Chế độ tệp, dấu thời gian và các siêu dữ liệu khác bị bỏ qua.
- Các thư mục rỗng (các mục có đường dẫn kết thúc bằng dấu gạch chéo) có thể được bao gồm trong các tệp zip mô-đun nhưng không được giải nén. Lệnh
gokhông bao gồm các thư mục rỗng trong các tệp zip mà nó tạo. - Các liên kết tượng trưng và các tệp bất thường khác bị bỏ qua khi tạo tệp zip, vì chúng không thể di chuyển giữa các hệ điều hành và hệ thống tệp, đồng thời không có cách di động nào để biểu diễn chúng trong định dạng tệp zip.
- Các tệp bên trong các thư mục có tên
vendorbị bỏ qua khi tạo tệp zip, vì các thư mụcvendorbên ngoài mô-đun chính không bao giờ được sử dụng. - Các tệp bên trong các thư mục chứa tệp
go.mod, ngoài thư mục gốc của mô-đun, bị bỏ qua khi tạo tệp zip, vì chúng không thuộc về mô-đun. Lệnhgobỏ qua các thư mục con chứa tệpgo.modkhi giải nén tệp zip. - Không có hai tệp nào trong một tệp zip có thể có đường dẫn giống nhau theo quy tắc gấp chữ hoa chữ thường Unicode (xem
strings.EqualFold). Điều này đảm bảo rằng các tệp zip có thể được giải nén trên các hệ thống tệp không phân biệt chữ hoa chữ thường mà không xảy ra xung đột. - Một tệp
go.modcó thể xuất hiện hoặc không xuất hiện trong thư mục cấp cao nhất ($module@$version/go.mod). Nếu có, nó phải có têngo.mod(toàn bộ chữ thường). Các tệp có têngo.modkhông được phép xuất hiện trong bất kỳ thư mục nào khác. - Tên tệp và thư mục trong một mô-đun có thể bao gồm các chữ cái Unicode, chữ số ASCII, ký tự khoảng trắng ASCII (U+0020) và các ký tự dấu câu ASCII
!#$%&()+,-.=@[]^_{}~. Lưu ý rằng đường dẫn gói có thể không chứa tất cả các ký tự này. Xemmodule.CheckFilePathvàmodule.CheckImportPathđể biết sự khác biệt. - Tên tệp hoặc thư mục cho đến dấu chấm đầu tiên không được là tên tệp dành riêng trên Windows, bất kể cách viết hoa chữ thường (
CON,com1,NuL, v.v.).
Mô-đun riêng tư
Các mô-đun Go thường được phát triển và phân phối trên các máy chủ kiểm soát phiên bản và proxy mô-đun không có sẵn trên Internet công cộng. Lệnh go có thể tải xuống và xây dựng các mô-đun từ nguồn riêng tư, mặc dù thường yêu cầu một số cấu hình.
Các biến môi trường dưới đây có thể được sử dụng để cấu hình quyền truy cập vào các mô-đun riêng tư. Xem Các biến môi trường để biết chi tiết. Xem thêm Quyền riêng tư để biết thông tin về việc kiểm soát thông tin được gửi đến các máy chủ công cộng.
GOPROXY— danh sách các URL proxy mô-đun. Lệnhgosẽ thử tải xuống mô-đun từ từng máy chủ theo thứ tự. Từ khóadirectyêu cầu lệnhgotải xuống mô-đun từ các repository kiểm soát phiên bản nơi chúng được phát triển thay vì sử dụng proxy.GOPRIVATE— danh sách các mẫu glob của tiền tố đường dẫn mô-đun nên được xem là riêng tư. Hoạt động như giá trị mặc định choGONOPROXYvàGONOSUMDB.GONOPROXY— danh sách các mẫu glob của tiền tố đường dẫn mô-đun không nên được tải xuống từ proxy. Lệnhgosẽ tải xuống các mô-đun khớp với mẫu từ các repository kiểm soát phiên bản nơi chúng được phát triển, bất kểGOPROXY.GONOSUMDB— danh sách các mẫu glob của tiền tố đường dẫn mô-đun không nên được kiểm tra bằng cơ sở dữ liệu checksum công cộng, sum.golang.org.GOINSECURE— danh sách các mẫu glob của tiền tố đường dẫn mô-đun có thể được truy xuất qua HTTP và các giao thức không an toàn khác.
Các biến này có thể được đặt trong môi trường phát triển (ví dụ: trong tệp .profile), hoặc có thể được đặt vĩnh viễn bằng go env -w.
Phần còn lại của mục này mô tả các mẫu phổ biến để cung cấp quyền truy cập vào các proxy mô-đun riêng tư và repository kiểm soát phiên bản.
Proxy riêng tư phục vụ tất cả mô-đun
Một máy chủ proxy riêng tư trung tâm phục vụ tất cả mô-đun (công cộng và riêng tư) cung cấp khả năng kiểm soát nhiều nhất cho quản trị viên và yêu cầu ít cấu hình nhất cho từng nhà phát triển.
Để cấu hình lệnh go sử dụng một máy chủ như vậy, hãy đặt các biến môi trường sau, thay thế https://proxy.corp.example.com bằng URL proxy của bạn và corp.example.com bằng tiền tố mô-đun của bạn:
GOPROXY=https://proxy.corp.example.com
GONOSUMDB=corp.example.com
Thiết lập GOPROXY yêu cầu lệnh go chỉ tải xuống mô-đun từ https://proxy.corp.example.com; lệnh go sẽ không kết nối với các proxy khác hoặc các repository kiểm soát phiên bản.
Thiết lập GONOSUMDB yêu cầu lệnh go không sử dụng cơ sở dữ liệu checksum công cộng để xác thực các mô-đun có đường dẫn bắt đầu bằng corp.example.com.
Một proxy chạy theo cấu hình này có thể cần quyền truy cập đọc vào các máy chủ kiểm soát phiên bản riêng tư. Proxy này cũng cần quyền truy cập Internet công cộng để tải xuống các phiên bản mới của các mô-đun công cộng.
Có một số triển khai máy chủ GOPROXY hiện có có thể được sử dụng theo cách này. Một triển khai tối thiểu sẽ phục vụ các tệp từ thư mục bộ nhớ đệm mô-đun và sẽ sử dụng go mod download (với cấu hình phù hợp) để truy xuất các mô-đun còn thiếu.
Proxy riêng tư phục vụ các mô-đun riêng tư
Một máy chủ proxy riêng tư có thể phục vụ các mô-đun riêng tư mà không đồng thời phục vụ các mô-đun có sẵn công khai. Lệnh go có thể được cấu hình để quay lại các nguồn công khai cho những mô-đun không có trên máy chủ riêng tư.
Để cấu hình lệnh go hoạt động theo cách này, hãy đặt các biến môi trường sau, thay thế https://proxy.corp.example.com bằng URL proxy và corp.example.com bằng tiền tố mô-đun:
GOPROXY=https://proxy.corp.example.com,https://proxy.golang.org,direct
GONOSUMDB=corp.example.com
Thiết lập GOPROXY hướng dẫn lệnh go thử tải xuống các mô-đun từ https://proxy.corp.example.com trước. Nếu máy chủ đó phản hồi với 404 (Not Found) hoặc 410 (Gone), lệnh go sẽ quay lại https://proxy.golang.org, sau đó kết nối trực tiếp đến các kho lưu trữ.
Thiết lập GONOSUMDB hướng dẫn lệnh go không sử dụng cơ sở dữ liệu tổng kiểm tra công khai để xác thực các mô-đun có đường dẫn bắt đầu bằng corp.example.com.
Lưu ý rằng một proxy được sử dụng trong cấu hình này vẫn có thể kiểm soát quyền truy cập vào các mô-đun công khai, dù nó không phục vụ các mô-đun đó. Nếu proxy phản hồi một yêu cầu bằng trạng thái lỗi khác ngoài 404 hoặc 410, lệnh go sẽ không quay lại các mục sau trong danh sách GOPROXY. Ví dụ: proxy có thể phản hồi 403 (Forbidden) đối với một mô-đun có giấy phép không phù hợp hoặc có lỗ hổng bảo mật đã biết.
Truy cập trực tiếp vào các mô-đun riêng tư
Lệnh go có thể được cấu hình để bỏ qua các proxy công khai và tải xuống các mô-đun riêng tư trực tiếp từ các máy chủ kiểm soát phiên bản. Điều này hữu ích khi việc chạy một máy chủ proxy riêng tư không khả thi.
Để cấu hình lệnh go hoạt động theo cách này, hãy đặt GOPRIVATE, thay thế corp.example.com bằng tiền tố mô-đun riêng tư:
GOPRIVATE=corp.example.com
Biến GOPROXY không cần thay đổi trong tình huống này. Giá trị mặc định của nó là https://proxy.golang.org,direct, giá trị này hướng dẫn lệnh go thử tải xuống các mô-đun từ https://proxy.golang.org trước, sau đó quay lại kết nối trực tiếp nếu proxy đó phản hồi với 404 (Not Found) hoặc 410 (Gone).
Thiết lập GOPRIVATE hướng dẫn lệnh go không kết nối tới proxy hoặc cơ sở dữ liệu tổng kiểm tra đối với các mô-đun bắt đầu bằng corp.example.com.
Một máy chủ HTTP nội bộ vẫn có thể cần thiết để giải quyết đường dẫn mô-đun thành URL kho lưu trữ. Ví dụ: khi lệnh go tải xuống mô-đun corp.example.com/mod, nó sẽ gửi một yêu cầu GET tới https://corp.example.com/mod?go-get=1, và tìm URL kho lưu trữ trong phản hồi. Để tránh yêu cầu này, hãy đảm bảo mỗi đường dẫn mô-đun riêng tư có hậu tố VCS (như .git) đánh dấu tiền tố gốc của kho lưu trữ. Ví dụ: khi lệnh go tải xuống mô-đun corp.example.com/repo.git/mod, nó sẽ sao chép kho lưu trữ Git tại https://corp.example.com/repo.git hoặc ssh://corp.example.com/repo.git mà không cần thực hiện thêm các yêu cầu khác.
Nhà phát triển sẽ cần quyền đọc đối với các kho lưu trữ chứa các mô-đun riêng tư. Điều này có thể được cấu hình trong các tệp cấu hình VCS toàn cục như .gitconfig. Tốt nhất là các công cụ VCS được cấu hình để không cần các lời nhắc xác thực tương tác. Theo mặc định, khi gọi Git, lệnh go vô hiệu hóa các lời nhắc tương tác bằng cách đặt GIT_TERMINAL_PROMPT=0, nhưng vẫn tôn trọng các thiết lập rõ ràng.
Truyền thông tin xác thực đến các proxy riêng tư
Lệnh go có thể xác thực với các máy chủ proxy bằng xác thực cơ bản HTTP hoặc các tiêu đề yêu cầu được cung cấp bởi GOAUTH.
Thông tin xác thực có thể được chỉ định trong một tệp .netrc.
Ví dụ: một tệp .netrc chứa các dòng bên dưới sẽ cấu hình lệnh go kết nối với máy proxy.corp.example.com bằng tên người dùng và mật khẩu đã cho.
machine proxy.corp.example.com
login jrgopher
password hunter2
Vị trí của tệp có thể được đặt bằng biến môi trường NETRC. Nếu NETRC không được đặt, lệnh go sẽ đọc $HOME/.netrc trên các nền tảng giống UNIX hoặc %USERPROFILE%\_netrc trên Windows.
Các trường trong .netrc được phân tách bằng dấu cách, tab và dòng mới. Đáng tiếc là các ký tự này không thể được sử dụng trong tên người dùng hoặc mật khẩu. Cũng lưu ý rằng tên máy không thể là một URL đầy đủ, vì vậy không thể chỉ định các tên người dùng và mật khẩu khác nhau cho các đường dẫn khác nhau trên cùng một máy.
Trong Go 1.24 trở lên, GOAUTH có thể sử dụng .netrc, chạy git credential fill trong một thư mục làm việc được chỉ định, hoặc gọi một lệnh tùy chỉnh. Một lệnh tùy chỉnh có thể cung cấp các tiêu đề yêu cầu HTTP tùy ý, chẳng hạn như mã thông báo Bearer, cho một hoặc nhiều tiền tố URL HTTPS. Điều này cho phép giới hạn phạm vi của thông tin xác thực theo một đường dẫn trên máy chủ proxy, điều mà .netrc không thể thực hiện. Xem go help goauth để biết giao thức lệnh và các tùy chọn cấu hình.
Lệnh go chỉ áp dụng thông tin xác thực thu được thông qua GOAUTH, bao gồm phương thức netrc mặc định của nó, cho các yêu cầu HTTPS.
Ngoài ra, thông tin xác thực có thể được chỉ định trực tiếp trong các URL GOPROXY. Ví dụ:
GOPROXY=https://jrgopher:hunter2@proxy.corp.example.com
Hãy cẩn thận khi sử dụng cách tiếp cận này: các biến môi trường có thể xuất hiện trong lịch sử shell và trong nhật ký.
Truyền thông tin xác thực đến các kho lưu trữ riêng tư
Lệnh go có thể tải xuống một module trực tiếp từ một kho lưu trữ kiểm soát phiên bản. Điều này cần thiết cho các module riêng tư nếu không sử dụng proxy riêng tư. Xem Truy cập trực tiếp vào các module riêng tư để biết cấu hình.
Lệnh go chạy các công cụ kiểm soát phiên bản như git khi tải xuống các module trực tiếp. Các công cụ này thực hiện việc xác thực riêng của chúng, vì vậy bạn có thể cần cấu hình thông tin xác thực trong một tệp cấu hình dành riêng cho công cụ như .gitconfig.
Để đảm bảo hoạt động trơn tru, hãy đảm bảo lệnh go sử dụng đúng URL của kho lưu trữ và công cụ kiểm soát phiên bản không yêu cầu nhập mật khẩu tương tác. Lệnh go ưu tiên các URL https:// hơn các lược đồ khác như ssh:// trừ khi lược đồ đã được chỉ định khi tra cứu URL của kho lưu trữ. Riêng với các kho lưu trữ GitHub, lệnh go giả định sử dụng https://.
Đối với hầu hết máy chủ, bạn có thể cấu hình máy khách để xác thực qua HTTP. Ví dụ: GitHub hỗ trợ sử dụng mã thông báo truy cập cá nhân OAuth làm mật khẩu HTTP.
Bạn có thể lưu trữ mật khẩu HTTP trong tệp .netrc, giống như khi truyền thông tin xác thực đến các proxy riêng tư.
Ngoài ra, bạn có thể viết lại các URL https:// thành một lược đồ khác. Ví dụ, trong .gitconfig:
[url "git@github.com:"]
insteadOf = https://github.com/
Để biết thêm thông tin, xem Tại sao “go get” sử dụng HTTPS khi sao chép một kho lưu trữ?
Quyền riêng tư
Lệnh go có thể tải xuống các module và metadata từ các máy chủ proxy module và các hệ thống quản lý phiên bản. Biến môi trường GOPROXY kiểm soát các máy chủ nào được sử dụng. Các biến môi trường GOPRIVATE và GONOPROXY kiểm soát những module nào được lấy từ proxy.
Giá trị mặc định của GOPROXY là:
https://proxy.golang.org,direct
Với thiết lập này, khi lệnh go tải xuống một module hoặc metadata của module, trước tiên nó sẽ gửi một yêu cầu đến proxy.golang.org, một proxy module công khai do Google vận hành (chính sách quyền riêng tư). Xem giao thức GOPROXY để biết chi tiết về thông tin được gửi trong mỗi yêu cầu. Lệnh go không truyền thông tin nhận dạng cá nhân, nhưng nó có truyền toàn bộ đường dẫn module đang được yêu cầu. Nếu proxy phản hồi với trạng thái 404 (Not Found) hoặc 410 (Gone), lệnh go sẽ cố gắng kết nối trực tiếp đến hệ thống quản lý phiên bản cung cấp module đó. Xem Các hệ thống quản lý phiên bản để biết chi tiết.
Các biến môi trường GOPRIVATE hoặc GONOPROXY có thể được đặt thành danh sách các mẫu glob khớp với tiền tố module là riêng tư và không nên được yêu cầu từ bất kỳ proxy nào. Ví dụ:
GOPRIVATE=*.corp.example.com,*.research.example.com
GOPRIVATE chỉ đơn giản hoạt động như giá trị mặc định cho GONOPROXY và GONOSUMDB, vì vậy không cần thiết lập GONOPROXY trừ khi GONOSUMDB cần có một giá trị khác. Khi đường dẫn module khớp với GONOPROXY, lệnh go bỏ qua GOPROXY đối với module đó và lấy module trực tiếp từ kho lưu trữ quản lý phiên bản của nó. Điều này hữu ích khi không có proxy nào phục vụ các module riêng tư. Xem Truy cập trực tiếp vào các module riêng tư.
Nếu có một proxy đáng tin cậy phục vụ tất cả module, thì không nên đặt GONOPROXY. Ví dụ, nếu GOPROXY được đặt thành một nguồn duy nhất, lệnh go sẽ không tải xuống module từ các nguồn khác. GONOSUMDB vẫn nên được đặt trong trường hợp này.
GOPROXY=https://proxy.corp.example.com
GONOSUMDB=*.corp.example.com,*.research.example.com
Nếu có một proxy đáng tin cậy chỉ phục vụ các module riêng tư, thì không nên đặt GONOPROXY, nhưng cần đảm bảo proxy phản hồi bằng các mã trạng thái chính xác. Ví dụ, hãy xem xét cấu hình sau:
GOPROXY=https://proxy.corp.example.com,https://proxy.golang.org
GONOSUMDB=*.corp.example.com,*.research.example.com
Giả sử rằng do một lỗi đánh máy, một nhà phát triển cố tải xuống một module không tồn tại.
go mod download corp.example.com/secret-product/typo@latest
Lệnh go trước tiên yêu cầu module này từ proxy.corp.example.com. Nếu proxy đó phản hồi với 404 (Not Found) hoặc 410 (Gone), lệnh go sẽ chuyển sang proxy.golang.org, truyền đường dẫn secret-product trong URL yêu cầu. Nếu proxy riêng tư phản hồi bằng bất kỳ mã lỗi nào khác, lệnh go sẽ in lỗi và không chuyển sang các nguồn khác.
Ngoài các proxy, lệnh go có thể kết nối đến cơ sở dữ liệu checksum để xác minh các hàm băm mật mã của những module không được liệt kê trong go.sum. Biến môi trường GOSUMDB thiết lập tên, URL và khóa công khai của cơ sở dữ liệu checksum. Giá trị mặc định của GOSUMDB là sum.golang.org, cơ sở dữ liệu checksum công khai do Google vận hành (chính sách quyền riêng tư). Xem Cơ sở dữ liệu checksum để biết chi tiết về những gì được truyền trong mỗi yêu cầu. Tương tự như proxy, lệnh go không truyền thông tin nhận dạng cá nhân, nhưng nó có truyền toàn bộ đường dẫn module đang được yêu cầu, và cơ sở dữ liệu checksum không thể tính checksum cho các module không công khai.
Biến môi trường GONOSUMDB có thể được đặt thành các mẫu cho biết những module nào là riêng tư và không nên được yêu cầu từ cơ sở dữ liệu checksum. GOPRIVATE hoạt động như giá trị mặc định cho GONOSUMDB và GONOPROXY, vì vậy không cần thiết lập GONOSUMDB trừ khi GONOPROXY cần có một giá trị khác.
Một proxy có thể phản chiếu cơ sở dữ liệu checksum. Nếu một proxy trong GOPROXY thực hiện điều này, lệnh go sẽ không kết nối trực tiếp đến cơ sở dữ liệu checksum.
GOSUMDB có thể được đặt thành off để vô hiệu hóa hoàn toàn việc sử dụng cơ sở dữ liệu checksum. Với thiết lập này, lệnh go sẽ không xác thực các module đã tải xuống trừ khi chúng đã có trong go.sum. Xem Xác thực module.
Bộ nhớ đệm module
The bộ nhớ đệm module là thư mục nơi lệnh go lưu trữ các tệp module đã tải xuống. Bộ nhớ đệm module khác với bộ nhớ đệm build, nơi chứa các gói đã biên dịch và các tạo tác build khác.
Vị trí mặc định của bộ nhớ đệm module là $GOPATH/pkg/mod. Để sử dụng vị trí khác, hãy đặt biến môi trường GOMODCACHE.
Bộ nhớ đệm module không có kích thước tối đa và lệnh go không tự động xóa nội dung của nó.
Bộ nhớ đệm có thể được chia sẻ bởi nhiều dự án Go được phát triển trên cùng một máy. Lệnh go sẽ sử dụng cùng một bộ nhớ đệm bất kể vị trí của module chính. Nhiều thực thể của lệnh go có thể truy cập an toàn cùng một bộ nhớ đệm module cùng lúc.
Lệnh go tạo các tệp nguồn module và thư mục trong bộ nhớ đệm với quyền chỉ đọc để ngăn việc vô tình thay đổi các module sau khi chúng được tải xuống. Điều này có tác dụng phụ không mong muốn là khiến việc xóa bộ nhớ đệm bằng các lệnh như rm -rf trở nên khó khăn. Thay vào đó, có thể xóa bộ nhớ đệm bằng go clean -modcache. Ngoài ra, khi sử dụng cờ -modcacherw, lệnh go sẽ tạo các thư mục mới với quyền đọc-ghi. Điều này làm tăng rủi ro trình soạn thảo, bài kiểm thử và các chương trình khác sửa đổi tệp trong bộ nhớ đệm module. Có thể sử dụng lệnh go mod verify để phát hiện các sửa đổi đối với các dependency của module chính. Lệnh này quét nội dung đã giải nén của từng dependency module và xác nhận chúng khớp với hash mong đợi trong go.sum.
Bảng bên dưới giải thích mục đích của hầu hết các tệp trong bộ nhớ đệm module. Một số tệp tạm thời (tệp khóa, thư mục tạm thời) được bỏ qua. Với mỗi đường dẫn, $module là đường dẫn module và $version là một phiên bản. Các đường dẫn kết thúc bằng dấu gạch chéo (/) là thư mục. Các chữ cái viết hoa trong đường dẫn module và phiên bản được escape bằng dấu chấm than (Azure được escape thành !azure) để tránh xung đột trên các hệ thống tệp không phân biệt chữ hoa chữ thường.
| Đường dẫn | Mô tả |
|---|---|
$module@$version/ |
Thư mục chứa nội dung đã giải nén của tệp .zip
module. Thư mục này đóng vai trò là thư mục gốc module cho một module đã
tải xuống. Nó sẽ không chứa tệp go.mod nếu module gốc
không có tệp đó.
|
cache/download/ |
Thư mục chứa các tệp được tải xuống từ proxy module và các tệp
được tạo ra từ hệ thống quản lý phiên bản. Bố cục của
thư mục này tuân theo
giao thức GOPROXY, vì vậy
thư mục này có thể được sử dụng làm proxy khi được phục vụ bởi một máy chủ
tệp HTTP hoặc khi được tham chiếu bằng URL file://.
|
cache/download/$module/@v/list |
Danh sách các phiên bản đã biết (xem
giao thức GOPROXY). Tệp này
có thể thay đổi theo thời gian, vì vậy lệnh go thường lấy
một bản sao mới thay vì sử dụng lại tệp này.
|
cache/download/$module/@v/$version.info |
Metadata JSON về phiên bản. (xem
giao thức GOPROXY). Tệp này
có thể thay đổi theo thời gian, vì vậy lệnh go thường lấy
một bản sao mới thay vì sử dụng lại tệp này.
|
cache/download/$module/@v/$version.mod |
Tệp go.mod cho phiên bản này (xem
giao thức GOPROXY). Nếu
module gốc không có tệp go.mod, đây là tệp được tổng hợp
không có yêu cầu nào.
|
cache/download/$module/@v/$version.zip |
Nội dung đã nén của module (xem
giao thức GOPROXY và
tệp zip module).
|
cache/download/$module/@v/$version.ziphash |
Một hash mật mã của các tệp trong tệp .zip.
Lưu ý rằng bản thân tệp .zip không được băm, vì vậy thứ
tự tệp, việc nén, căn chỉnh và metadata không ảnh hưởng đến hash.
Khi sử dụng một module, lệnh go xác minh hash này
khớp với dòng tương ứng trong
go.sum. Lệnh
go mod verify kiểm tra
rằng các hash của tệp .zip module và các thư mục đã giải
nén khớp với các tệp này.
|
cache/download/sumdb/ |
Thư mục chứa các tệp được tải xuống từ một
cơ sở dữ liệu checksum (thường là
sum.golang.org).
|
cache/vcs/ |
Chứa các kho lưu trữ repository được clone của các module được lấy trực tiếp từ nguồn của chúng. Tên thư mục là các hash được mã hóa hexa, được tạo ra từ loại repository và URL. Các repository được tối ưu để giảm kích thước trên đĩa. Ví dụ, các repository Git được clone là dạng bare và shallow khi có thể. |
Xác thực module
Khi lệnh go tải xuống tệp zip của module hoặc tệp go.mod vào bộ nhớ đệm module, nó tính toán một hàm băm mật mã và so sánh với một giá trị đã biết để xác minh rằng tệp chưa bị thay đổi kể từ lần đầu được tải xuống. Lệnh go báo lỗi bảo mật nếu tệp đã tải xuống không có hàm băm chính xác.
Đối với các tệp go.mod, lệnh go tính hàm băm từ nội dung tệp. Đối với các tệp zip của module, lệnh go tính hàm băm từ tên và nội dung của các tệp bên trong kho lưu trữ theo một thứ tự xác định. Hàm băm không bị ảnh hưởng bởi thứ tự tệp, việc nén, căn chỉnh và các siêu dữ liệu khác. Xem golang.org/x/mod/sumdb/dirhash để biết chi tiết về cách triển khai hàm băm.
Lệnh go so sánh từng hàm băm với dòng tương ứng trong tệp go.sum của module chính. Nếu hàm băm khác với hàm băm trong go.sum, lệnh go báo lỗi bảo mật và xóa tệp đã tải xuống mà không thêm tệp đó vào bộ nhớ đệm module.
Nếu tệp go.sum không tồn tại, hoặc không chứa hàm băm cho tệp đã tải xuống, lệnh go có thể xác minh hàm băm bằng cách sử dụng cơ sở dữ liệu checksum, một nguồn hàm băm toàn cục cho các module công khai. Sau khi hàm băm được xác minh, lệnh go thêm nó vào go.sum và thêm tệp đã tải xuống vào bộ nhớ đệm module. Nếu một module là riêng tư (được khớp bởi các biến môi trường GOPRIVATE hoặc GONOSUMDB) hoặc nếu cơ sở dữ liệu checksum bị vô hiệu hóa (bằng cách đặt GOSUMDB=off), lệnh go chấp nhận hàm băm và thêm tệp vào bộ nhớ đệm module mà không xác minh nó.
Bộ nhớ đệm module thường được chia sẻ bởi tất cả các dự án Go trên một hệ thống, và mỗi module có thể có tệp go.sum riêng với các hàm băm có khả năng khác nhau. Để tránh cần phải tin cậy các module khác, lệnh go xác minh các hàm băm bằng cách sử dụng go.sum của module chính mỗi khi truy cập một tệp trong bộ nhớ đệm module. Việc tính hàm băm cho tệp zip tốn nhiều chi phí, vì vậy lệnh go kiểm tra các hàm băm đã được tính trước được lưu bên cạnh các tệp zip thay vì tính lại hàm băm của các tệp. Lệnh go mod verify có thể được sử dụng để kiểm tra rằng các tệp zip và thư mục đã giải nén chưa bị sửa đổi kể từ khi chúng được thêm vào bộ nhớ đệm module.
go.sum files
Một module có thể có một tệp văn bản tên là go.sum trong thư mục gốc, cùng với tệp go.mod của nó. Tệp go.sum chứa các hàm băm mật mã của các dependency trực tiếp và gián tiếp của module. Khi lệnh go tải xuống tệp .mod hoặc .zip của một module vào bộ nhớ đệm module, nó tính toán một hàm băm và kiểm tra rằng hàm băm đó khớp với hàm băm tương ứng trong tệp go.sum của module chính. go.sum có thể trống hoặc không tồn tại nếu module không có dependency hoặc nếu tất cả dependency được thay thế bằng các thư mục cục bộ bằng cách sử dụng các chỉ thị replace.
Mỗi dòng trong go.sum có ba trường được phân tách bằng dấu cách: đường dẫn module, một phiên bản (có thể kết thúc bằng /go.mod) và một hàm băm.
- Đường dẫn module là tên của module mà hàm băm thuộc về.
- Phiên bản là phiên bản của module mà hàm băm thuộc về. Nếu phiên bản kết thúc bằng
/go.mod, hàm băm chỉ dành cho tệpgo.modcủa module; nếu không, hàm băm dành cho các tệp bên trong tệp.zipcủa module. - Cột hàm băm bao gồm tên của một thuật toán (như
h1) và một hàm băm mật mã được mã hóa bằng base64, được phân tách bằng dấu hai chấm (:). Hiện tại, SHA-256 (h1) là thuật toán băm duy nhất được hỗ trợ. Nếu phát hiện lỗ hổng bảo mật trong SHA-256 trong tương lai, hỗ trợ sẽ được thêm cho một thuật toán khác (có tênh2và tương tự).
Tệp go.sum có thể chứa các hàm băm cho nhiều phiên bản của một module. Lệnh go có thể cần tải các tệp go.mod từ nhiều phiên bản của một dependency để thực hiện lựa chọn phiên bản tối thiểu. go.sum cũng có thể chứa các hàm băm cho những phiên bản module không còn cần thiết nữa (ví dụ: sau khi nâng cấp). go mod tidy sẽ thêm các hàm băm bị thiếu và sẽ xóa các hàm băm không cần thiết khỏi go.sum.
Cơ sở dữ liệu checksum
Cơ sở dữ liệu checksum là nguồn toàn cục của các dòng go.sum. Lệnh go có thể sử dụng nguồn này trong nhiều tình huống để phát hiện hành vi sai của proxy hoặc máy chủ gốc.
Cơ sở dữ liệu checksum cho phép tính nhất quán và độ tin cậy toàn cục cho tất cả các phiên bản module công khai. Nó làm cho các proxy không đáng tin cậy trở nên khả thi vì chúng không thể cung cấp mã sai mà không bị phát hiện. Nó cũng đảm bảo rằng các bit liên quan đến một phiên bản cụ thể không thay đổi từ ngày này sang ngày khác, ngay cả khi tác giả của module sau đó thay đổi các thẻ trong kho lưu trữ của họ.
Cơ sở dữ liệu checksum được cung cấp bởi sum.golang.org, do Google vận hành. Đây là một Nhật ký minh bạch (hay “Cây Merkle”) của các hàm băm dòng go.sum, được hỗ trợ bởi Trillian. Ưu điểm chính của cây Merkle là các kiểm toán viên độc lập có thể xác minh rằng nó chưa bị can thiệp, vì vậy nó đáng tin cậy hơn một cơ sở dữ liệu đơn giản.
Lệnh go tương tác với cơ sở dữ liệu checksum bằng giao thức được mô tả ban đầu trong Đề xuất: Bảo mật Hệ sinh thái Module Go công khai.
Bảng bên dưới chỉ rõ các truy vấn mà cơ sở dữ liệu checksum phải phản hồi. Với mỗi đường dẫn, $base là phần đường dẫn của URL cơ sở dữ liệu checksum, $module là một đường dẫn module và $version là một phiên bản. Ví dụ: nếu URL cơ sở dữ liệu checksum là https://sum.golang.org, và máy khách đang yêu cầu bản ghi cho module golang.org/x/text ở phiên bản v0.3.2, máy khách sẽ gửi một yêu cầu GET tới
https://sum.golang.org/lookup/golang.org/x/text@v0.3.2.
Để tránh sự không rõ ràng khi phục vụ từ các hệ thống tệp không phân biệt chữ hoa chữ thường, các phần tử $module và $version được mã hóa phân biệt chữ hoa chữ thường bằng cách thay thế mọi chữ cái viết hoa bằng một dấu chấm than theo sau bởi chữ cái viết thường tương ứng. Điều này cho phép các module example.com/M và example.com/m đều được lưu trữ trên đĩa, vì module trước được mã hóa thành example.com/!m.
Các phần của đường dẫn được bao quanh bởi dấu ngoặc vuông, như [.p/$W], biểu thị các giá trị tùy chọn.
| Đường dẫn | Mô tả |
|---|---|
$base/latest |
Trả về mô tả cây đã mã hóa, được ký cho nhật ký mới nhất. Mô tả đã ký này có dạng
note,
là văn bản đã được ký bởi một hoặc nhiều khóa máy chủ và có thể được xác minh bằng khóa công khai của máy chủ. Mô tả cây cung cấp kích thước của cây và hàm băm của đầu cây tại kích thước đó. Cách mã hóa này được mô tả trong
golang.org/x/mod/sumdb/tlog#FormatTree.
|
$base/lookup/$module@$version |
Trả về số bản ghi nhật ký cho mục nhập về $module
tại $version, tiếp theo là dữ liệu của bản ghi (nghĩa là
các dòng go.sum cho $module tại
$version) và mô tả cây đã mã hóa, được ký, chứa bản ghi đó.
|
$base/tile/$H/$L/$K[.p/$W] |
Trả về một mảnh nhật ký,
là một tập hợp các hàm băm tạo thành một phần của nhật ký. Mỗi mảnh
được xác định trong tọa độ hai chiều tại mức mảnh
$L, thứ $K tính từ bên trái, với chiều cao mảnh
là $H. Hậu tố tùy chọn .p/$W chỉ ra một
mảnh nhật ký từng phần chỉ có $W hàm băm. Máy khách phải
quay lại lấy mảnh đầy đủ nếu không tìm thấy mảnh từng phần.
|
$base/tile/$H/data/$K[.p/$W] |
Trả về dữ liệu bản ghi cho các hàm băm lá trong
/tile/$H/0/$K[.p/$W] (với phần tử đường dẫn
data theo nghĩa đen).
|
Nếu lệnh go tham vấn cơ sở dữ liệu tổng kiểm tra, thì bước đầu tiên là truy xuất dữ liệu bản ghi thông qua điểm cuối /lookup. Nếu phiên bản mô-đun chưa được ghi vào nhật ký, cơ sở dữ liệu tổng kiểm tra sẽ thử lấy nó từ máy chủ gốc trước khi trả lời. Dữ liệu /lookup này cung cấp tổng cho phiên bản mô-đun này cũng như vị trí của nó trong nhật ký, cho máy khách biết những mảnh nào cần được lấy để thực hiện các bằng chứng. Lệnh go thực hiện các bằng chứng “bao gồm” (rằng một bản ghi cụ thể tồn tại trong nhật ký) và các bằng chứng “nhất quán” (rằng cây chưa bị can thiệp) trước khi thêm các dòng go.sum mới vào tệp go.sum của mô-đun chính. Điều quan trọng là dữ liệu từ /lookup không bao giờ được sử dụng nếu chưa xác thực nó với hàm băm cây đã ký và xác thực hàm băm cây đã ký với chuỗi thời gian của các hàm băm cây đã ký của máy khách.
Các hàm băm cây đã ký và các mảnh mới do cơ sở dữ liệu tổng kiểm tra cung cấp được lưu trong bộ đệm mô-đun, vì vậy lệnh go chỉ cần lấy các mảnh còn thiếu.
Lệnh go không cần kết nối trực tiếp với cơ sở dữ liệu tổng kiểm tra. Nó có thể yêu cầu tổng mô-đun thông qua một proxy mô-đun
phản chiếu cơ sở dữ liệu tổng kiểm tra
và hỗ trợ giao thức ở trên. Điều này có thể đặc biệt hữu ích cho các proxy riêng tư, proxy của doanh nghiệp chặn các yêu cầu bên ngoài tổ chức.
Biến môi trường GOSUMDB xác định tên của cơ sở dữ liệu tổng kiểm tra cần sử dụng và tùy chọn khóa công khai cùng URL của nó, như sau:
GOSUMDB="sum.golang.org"
GOSUMDB="sum.golang.org+<publickey>"
GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
Lệnh go biết khóa công khai của sum.golang.org, đồng thời biết rằng tên sum.golang.google.cn (có sẵn bên trong Trung Quốc đại lục) kết nối với cơ sở dữ liệu tổng kiểm tra sum.golang.org; việc sử dụng bất kỳ cơ sở dữ liệu nào khác yêu cầu cung cấp rõ ràng khóa công khai. URL mặc định là https:// theo sau bởi tên cơ sở dữ liệu.
GOSUMDB mặc định là sum.golang.org, cơ sở dữ liệu tổng kiểm tra Go do Google vận hành. Xem https://sum.golang.org/privacy để biết chính sách quyền riêng tư của dịch vụ.
Nếu GOSUMDB được đặt thành off, hoặc nếu go get được gọi với cờ -insecure, cơ sở dữ liệu tổng kiểm tra sẽ không được tham vấn và tất cả mô-đun chưa được nhận dạng sẽ được chấp nhận, phải đánh đổi bằng việc từ bỏ đảm bảo bảo mật về các lượt tải xuống có thể lặp lại đã được xác minh cho tất cả mô-đun. Cách tốt hơn để bỏ qua cơ sở dữ liệu tổng kiểm tra cho các mô-đun cụ thể là sử dụng các biến môi trường GOPRIVATE hoặc GONOSUMDB. Xem Mô-đun riêng tư để biết chi tiết.
Có thể sử dụng lệnh go env -w để
đặt các biến này
cho các lần gọi lệnh go trong tương lai.
Biến môi trường
Hành vi của module trong lệnh go có thể được cấu hình bằng các biến môi trường được liệt kê bên dưới. Danh sách này chỉ bao gồm các biến môi trường liên quan đến module. Xem go help environment để biết danh sách
tất cả các biến môi trường được lệnh go nhận dạng.
| Biến | Mô tả |
|---|---|
GO111MODULE |
Kiểm soát việc lệnh
Xem Các lệnh nhận biết module để biết thêm thông tin. |
GOMODCACHE |
Thư mục nơi lệnh
Nếu |
GOINSECURE |
Danh sách các mẫu glob được phân tách bằng dấu phẩy (theo cú pháp
của
Không giống cờ |
GONOPROXY |
Danh sách các mẫu glob được phân tách bằng dấu phẩy (theo cú pháp
của
Nếu |
GONOSUMDB |
Danh sách các mẫu glob được phân tách bằng dấu phẩy (theo cú pháp
của
Nếu |
GOPATH |
Ở chế độ
Ở chế độ nhận biết module, bộ nhớ đệm
module được lưu trong thư mục con
Nếu |
GOPRIVATE |
Danh sách các mẫu glob được phân tách bằng dấu phẩy (theo cú pháp của Go's
path.Match) gồm các tiền tố
đường dẫn module nên được xem là riêng tư. GOPRIVATE
là giá trị mặc định cho GONOPROXY và
GONOSUMDB. Xem
Quyền riêng tư. GOPRIVATE
cũng xác định liệu một module có được xem là riêng tư đối với
GOVCS hay không.
|
GOPROXY |
Danh sách các URL proxy module, được phân tách bằng dấu phẩy
(
Cách xử lý dự phòng khi gặp lỗi của lệnh
URL GOPROXY=file://$(go env GOMODCACHE)/cache/download Có thể dùng hai từ khóa thay cho URL proxy:
Xem Proxy module và Giải quyết một gói thành một module để biết thêm thông tin về cách proxy được sử dụng. |
GOSUMDB |
Xác định tên của cơ sở dữ liệu checksum được sử dụng và tùy chọn cả khóa công khai cùng URL của nó. Ví dụ: GOSUMDB="sum.golang.org" GOSUMDB="sum.golang.org+<publickey>" GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
Lệnh
Nếu Xem Xác thực module và Quyền riêng tư để biết thêm thông tin. |
GOVCS |
Kiểm soát tập hợp các công cụ kiểm soát phiên bản mà lệnh
Nếu public:git|hg,private:all
Xem Kiểm soát các công cụ kiểm soát phiên bản với
|
GOWORK |
Biến môi trường |
Bảng thuật ngữ
build constraint: Một điều kiện xác định liệu tệp nguồn Go có được sử dụng khi biên dịch một package hay không. Các build constraint có thể được biểu diễn bằng hậu tố tên tệp (ví dụ: foo_linux_amd64.go) hoặc bằng các chú thích build constraint (ví dụ: // +build linux,amd64). Xem Build
Constraints.
build list: Danh sách các phiên bản module sẽ được sử dụng cho một lệnh build như go build, go list hoặc go test. Build list được xác định từ module chính tệp go.mod và các tệp go.mod trong các module được yêu cầu bắc cầu bằng cách sử dụng minimal version selection. Build list chứa phiên bản của tất cả module trong đồ thị module, không chỉ những module liên quan đến một lệnh cụ thể.
canonical version: Một version có định dạng đúng, không có hậu tố metadata build nào khác ngoài +incompatible. Ví dụ, v1.2.3 là một canonical version, nhưng v1.2.3+meta thì không.
current module: Từ đồng nghĩa với module chính.
deprecated module: Một module không còn được các tác giả của nó hỗ trợ nữa (mặc dù các phiên bản major được xem là các module riêng biệt cho mục đích này). Một deprecated module được đánh dấu bằng chú thích deprecated trong phiên bản mới nhất của tệp go.mod của nó.
direct dependency: Một package có đường dẫn xuất hiện trong khai báo import trong tệp nguồn .go của một package hoặc test trong module chính, hoặc module chứa package đó. (So sánh với indirect dependency.)
direct mode: Một thiết lập của biến môi trường khiến lệnh go tải xuống một module trực tiếp từ hệ thống quản lý phiên bản, thay vì từ module proxy. GOPROXY=direct thực hiện điều này cho tất cả module. GOPRIVATE và GONOPROXY thực hiện điều này cho các module khớp với một danh sách mẫu.
go.mod file: Tệp định nghĩa đường dẫn, các yêu cầu và metadata khác của một module. Xuất hiện trong thư mục gốc của module. Xem phần về các tệp go.mod.
go.work file Tệp định nghĩa tập hợp các module được sử dụng trong một workspace. Xem phần về các tệp go.work
import path: Một chuỗi được dùng để import một package trong tệp nguồn Go. Đồng nghĩa với package path.
indirect dependency: Một package được import bắc cầu bởi một package hoặc test trong module chính, nhưng đường dẫn của nó không xuất hiện trong bất kỳ khai báo import nào trong module chính; hoặc một module xuất hiện trong đồ thị module nhưng không cung cấp package nào được module chính import trực tiếp.
(So sánh với direct dependency.)
lazy module loading: Một thay đổi trong Go 1.17 giúp tránh tải đồ thị module cho các lệnh không cần đến nó trong những module chỉ định go 1.17 hoặc cao hơn. Xem Lazy module loading.
main module: Module mà trong đó lệnh go được gọi. Module chính được định nghĩa bởi một tệp go.mod trong thư mục hiện tại hoặc thư mục cha. Xem Modules, packages, and
versions.
major version: Số đầu tiên trong một semantic version (1 trong v1.2.3). Trong một bản phát hành có các thay đổi không tương thích, major version phải được tăng lên, còn minor version và patch version phải được đặt thành 0. Các semantic version có major version bằng 0 được xem là không ổn định.
major version subdirectory: Một thư mục con trong một repository quản lý phiên bản khớp với hậu tố major version của một module, nơi module có thể được định nghĩa. Ví dụ, module example.com/mod/v2 trong repository có đường dẫn gốc example.com/mod có thể được định nghĩa trong thư mục gốc của repository hoặc thư mục con major version v2. Xem Module directories within a repository.
major version suffix: Một hậu tố đường dẫn module khớp với số major version. Ví dụ, /v2 trong example.com/mod/v2. Các major version suffix được yêu cầu ở v2.0.0 và các phiên bản sau đó, đồng thời không được phép ở các phiên bản trước đó. Xem phần về Major version suffixes.
minimal version selection (MVS): Thuật toán được sử dụng để xác định phiên bản của tất cả module sẽ được dùng trong một bản build. Xem phần Minimal version selection để biết chi tiết.
minor version: Số thứ hai trong một semantic version (2 trong v1.2.3). Trong một bản phát hành có chức năng mới tương thích ngược, minor version phải được tăng lên và patch version phải được đặt thành 0.
module: Một tập hợp các package được phát hành, đánh version và phân phối cùng nhau.
module cache: Một thư mục cục bộ lưu trữ các module đã tải xuống, nằm tại GOPATH/pkg/mod. Xem Module cache.
đồ thị module: Đồ thị có hướng của các yêu cầu module, bắt nguồn từ module chính. Mỗi đỉnh trong đồ thị là một module; mỗi cạnh là một phiên bản từ câu lệnh require trong tệp go.mod (chịu sự chi phối của các câu lệnh replace và exclude trong tệp go.mod của module chính).
cắt tỉa đồ thị module: Một thay đổi trong Go 1.17 giúp giảm kích thước của đồ thị module bằng cách loại bỏ các dependency bắc cầu của những module chỉ định go 1.17 hoặc cao hơn. Xem Cắt tỉa đồ thị module.
đường dẫn module: Một đường dẫn xác định một module và đóng vai trò tiền tố cho các đường dẫn import package bên trong module. Ví dụ: "golang.org/x/net".
proxy module: Một máy chủ web triển khai giao thức GOPROXY. Lệnh go tải thông tin phiên bản, các tệp go.mod và các tệp zip module từ các proxy module.
thư mục gốc module: Thư mục chứa tệp go.mod định nghĩa một module.
thư mục con module: Phần của đường dẫn module nằm sau đường dẫn gốc repository, cho biết thư mục con nơi module được định nghĩa. Khi không rỗng, thư mục con module cũng là tiền tố cho thẻ phiên bản semantic. Thư mục con module không bao gồm hậu tố phiên bản chính, nếu có, ngay cả khi module nằm trong thư mục con phiên bản chính. Xem Đường dẫn module.
package: Một tập hợp các tệp mã nguồn trong cùng một thư mục được biên dịch cùng nhau. Xem phần Packages trong Đặc tả ngôn ngữ Go.
đường dẫn package: Đường dẫn xác định duy nhất một package. Đường dẫn package là một đường dẫn module được nối với một thư mục con bên trong module. Ví dụ, "golang.org/x/net/html" là đường dẫn package cho package trong module "golang.org/x/net" ở thư mục con "html". Đồng nghĩa với đường dẫn import.
phiên bản patch: Số thứ ba trong một phiên bản semantic (3 trong v1.2.3). Trong một bản phát hành không có thay đổi đối với interface công khai của module, phiên bản patch phải được tăng lên.
phiên bản pre-release: Một phiên bản có dấu gạch ngang theo sau là một chuỗi định danh được phân tách bằng dấu chấm ngay sau phiên bản patch, ví dụ v1.2.3-beta4. Các phiên bản pre-release được xem là không ổn định và không được giả định là tương thích với các phiên bản khác. Một phiên bản pre-release được sắp xếp trước phiên bản phát hành tương ứng: v1.2.3-pre đứng trước v1.2.3. Xem thêm phiên bản bản phát hành.
phiên bản giả: Một phiên bản mã hóa định danh revision (chẳng hạn như hash commit Git) và dấu thời gian từ một hệ thống quản lý phiên bản. Ví dụ, v0.0.0-20191109021931-daa7c04131f5. Được dùng để tương thích với các repository không dùng module và trong các tình huống khác khi không có phiên bản được gắn thẻ.
phiên bản bản phát hành: Một phiên bản không có hậu tố pre-release. Ví dụ, v1.2.3, không phải v1.2.3-pre. Xem thêm phiên bản pre-release.
đường dẫn gốc repository: Phần của đường dẫn module tương ứng với thư mục gốc của một repository quản lý phiên bản. Xem Đường dẫn module.
phiên bản bị thu hồi: Một phiên bản không nên được phụ thuộc vào, vì nó được phát hành quá sớm hoặc vì một vấn đề nghiêm trọng được phát hiện sau khi nó được phát hành. Xem chỉ thị retract.
thẻ phiên bản semantic: Một thẻ trong repository quản lý phiên bản ánh xạ một phiên bản tới một revision cụ thể. Xem Ánh xạ phiên bản tới commit.
phiên bản được chọn: Phiên bản của một module cụ thể được chọn bởi lựa chọn phiên bản tối thiểu. Phiên bản được chọn là phiên bản cao nhất cho đường dẫn của module được tìm thấy trong đồ thị module.
thư mục vendor: Một thư mục có tên vendor chứa các package từ các module khác cần thiết để xây dựng các package trong module chính. Được duy trì bằng go mod vendor. Xem Vendoring.
phiên bản: Một định danh cho ảnh chụp bất biến của một module, được viết dưới dạng chữ v theo sau bởi một phiên bản semantic. Xem phần Các phiên bản.
workspace: Một tập hợp các module trên đĩa được sử dụng làm các module chính khi chạy lựa chọn phiên bản tối thiểu (MVS). Xem phần Workspace