Tổng quan
Đây là một bố cục cơ bản cho các dự án ứng dụng Go. Đây không phải là một tiêu chuẩn được xác định chính thức bởi nhóm phát triển lõi Go; đây là một cấu trúc thư mục thông thường được sử dụng cho các dự án Go trong cộng đồng.
Nếu bạn đang học Go hoặc xây dựng một bản chứng minh (PoC) hoặc một dự án cá nhân đơn giản, cấu trúc dự án này quá phức tạp. Thay vào đó, bắt đầu với một cấu trúc đơn giản thực sự (chỉ cần một tệp main.go
và go.mod
là đủ). Khi dự án của bạn phát triển, hãy đảm bảo cấu trúc mã nguồn của bạn tốt, nếu không bạn sẽ kết thúc với mã nguồn lộn xộn chứa rất nhiều phụ thuộc ẩn và trạng thái toàn cục. Khi nhiều người tham gia dự án, bạn cần một cách tổ chức có cấu trúc hơn. Trong trường hợp này, việc giới thiệu một cách quản lý chung cho các gói/thư viện là rất quan trọng. Khi bạn có một dự án mã nguồn mở hoặc biết rằng các dự án khác nhập mã nguồn từ kho lưu trữ dự án của bạn, việc có các gói và mã nguồn riêng tư (còn được gọi là internal
) trở nên quan trọng. Sao chép kho lưu trữ, giữ các phần bạn cần và xóa hết mọi thứ khác! Chỉ vì nó tồn tại không có nghĩa là bạn phải sử dụng hết. Không có mẫu cấu trúc nào được sử dụng trong mọi dự án. Ngay cả mô hình vendor
cũng không phải là phổ quát.
Cấu trúc dự án này được thiết kế một cách tỉ mỉ để làm cho nó rất chung chung và không cố gắng áp đặt một cấu trúc gói Go cụ thể.
Quy định Thư mục Dự án Go
Dưới đây là quy định thư mục dự án Go được khuyến nghị.
.
├── go.mod
├── api
├── assets
├── build
├── cmd
├── configs
├── deployments
├── docs
├── examples
├── githooks
├── go.mod
├── init
├── internal
├── pkg
├── scripts
├── test
├── third_party
├── tools
├── vendor
├── web
└── website
Ý nghĩa của mỗi thư mục sẽ được giới thiệu dưới đây.
/cmd
Các ứng dụng chính cho dự án, tức là điểm vào của các chương trình. Các tệp Go trong thư mục này thường tạo ra các tệp thực thi. Trong một dự án đơn giản, một tệp như /cmd/main.go
có thể phục vụ làm điểm vào.
Tên thư mục cho mỗi ứng dụng nên phù hợp với tên tệp thực thi bạn muốn (ví dụ, /cmd/myapp
).
Không đặt quá nhiều mã trong thư mục ứng dụng. Nếu bạn nghĩ rằng mã có thể được nhập và sử dụng trong các dự án khác, đặt nó trong thư mục /pkg
. Nếu mã không thể tái sử dụng hoặc bạn không muốn người khác tái sử dụng nó, đặt mã vào thư mục /internal
. Bạn sẽ ngạc nhiên với hành vi của người khác, vì vậy hãy diễn đạt ý định của bạn một cách rõ ràng!
Thường có một hàm main
nhỏ nhập và gọi mã từ các thư mục /internal
và /pkg
, và không có gì khác.
/internal
Mã ứng dụng và thư viện riêng tư. Đây là mã mà bạn không muốn người khác nhập vào ứng dụng hoặc thư viện của họ. Lưu ý rằng mẫu cấu trúc này được thiết lập bởi chính bộ biên dịch Go. Để biết thêm thông tin chi tiết, vui lòng tham khảo ghi chú phát hành cho Go 1.4. Lưu ý rằng điều này không giới hạn ở thư mục internal
cấp cao nhất. Bạn có thể có nhiều thư mục internal
ở bất kỳ cấp độ nào của cây dự án.
Bạn có thể chọn thêm một số cấu trúc bổ sung cho các gói nội bộ để phân biệt giữa mã nội bộ được chia sẻ và không được chia sẻ. Điều này không bắt buộc (đặc biệt là đối với các dự án nhỏ), nhưng thể hiện mô tả mục đích sử dụng gói một cách trực quan là một thực hành tốt. Mã ứng dụng thực tế của bạn có thể được đặt trong thư mục /internal/app
(ví dụ, /internal/app/myapp
), và mã được chia sẻ cho các ứng dụng này có thể được đặt trong thư mục /internal/pkg
(ví dụ, /internal/pkg/myprivlib
).
/pkg
Mã thư viện có thể được sử dụng bởi các ứng dụng bên ngoài (ví dụ, /pkg/mypubliclib
). Các dự án khác sẽ nhập các thư viện này và mong đợi chúng hoạt động một cách đúng đắn, vì vậy hãy cân nhắc kỹ trước khi đặt nội dung ở đây :-) Lưu ý rằng thư mục internal
là một cách tốt hơn để đảm bảo rằng các gói riêng tư không thể được nhập, vì nó được bắt buộc bởi chính Go. Thư mục /pkg
vẫn là một cách tốt để truyền đạt một cách rõ ràng rằng mã trong thư mục này an toàn để người khác sử dụng.
Nếu dự án ứng dụng của bạn rất nhỏ và việc lồng ghép nhiều cấp không thêm nhiều giá trị, không sử dụng nó cũng được (trừ khi bạn thực sự muốn sử dụng nó :-) ). Khi dự án trở nên lớn và thư mục gốc trở nên rất bận rộn, hãy xem xét sử dụng nó (đặc biệt nếu bạn có nhiều thành phần ứng dụng không phải Go).
/vendor
Các phụ thuộc ứng dụng (được quản lý thủ công hoặc sử dụng công cụ quản lý phụ thuộc ưa thích của bạn, như tính năng Go Modules
tích hợp). Lệnh go mod vendor
sẽ tạo thư mục /vendor
cho bạn. Lưu ý rằng nếu bạn không sử dụng phiên bản mặc định Go 1.14, bạn có thể cần thêm cờ -mod=vendor
vào lệnh go build
.
Nếu bạn đang xây dựng một thư viện, vui lòng không commit các phụ thuộc ứng dụng của bạn.
Thư mục Ứng dụng Dịch vụ
/api
Thông số kỹ thuật OpenAPI/Swagger, tệp schema JSON, tệp định nghĩa giao thức và thư mục giao thức API.
Thư mục Ứng dụng Web
/web
Các thành phần cụ thể cho ứng dụng web: tài sản trang web tĩnh, mẫu phía máy chủ, và ứng dụng trang đơn (SPAs).
Thư mục Ứng dụng Cơ bản
/configs
Mẫu tệp cấu hình hoặc cấu hình mặc định.
Đặt tệp mẫu confd
hoặc consul-template
vào đây.
/init
Khởi tạo hệ thống (systemd, upstart, sysv) và cấu hình quản lý quá trình/daemon (runit, supervisord).
/scripts
Các tập lệnh cho các quá trình xây dựng, cài đặt, phân tích và các hoạt động khác.
/build
Đóng gói và tích hợp liên tục.
Đặt cấu hình gói đám mây (AMI), container (Docker), hệ điều hành (deb, rpm, pkg) và tập lệnh trong thư mục /build/package
.
Đặt cấu hình và tập lệnh tích hợp liên tục (travis, circle, drone) vào thư mục /build/ci
. Vui lòng lưu ý rằng một số công cụ tích hợp liên tục (như Travis CI) rất cụ thể về vị trí các tệp cấu hình của chúng. Hãy thử đặt các tệp cấu hình trong thư mục /build/ci
và sử dụng liên kết để kết nối chúng với vị trí mà công cụ tích hợp liên tục mong đợi (nếu có thể).
/deployments
Cấu hình triển khai và mẫu cho IaaS, PaaS, hệ thống và triển khai container (docker-compose, kubernetes/helm, terraform). Vui lòng lưu ý rằng trong một số kho lưu trữ (đặc biệt là cho các ứng dụng triển khai bằng Kubernetes), thư mục này có thể được gọi là /deploy
.
/test
Các ứng dụng kiểm thử bên ngoài và dữ liệu kiểm thử. Hãy tự do tổ chức thư mục /test
theo cách phù hợp với nhu cầu của bạn. Đối với các dự án lớn, việc tổ chức dữ liệu thành các thư mục con có ý nghĩa. Ví dụ, bạn có thể tạo các thư mục /test/data
hoặc /test/testdata
bên trong /test
để Go bỏ qua nội dung này. Vui lòng lưu ý rằng Go cũng bỏ qua các thư mục hoặc tệp bắt đầu bằng "." hoặc "_", cung cấp tính linh hoạt hơn khi đặt tên cho các thư mục dữ liệu kiểm thử.
Các Thư mục Khác
/docs
Tài liệu thiết kế và người dùng (ngoài các tài liệu godoc bạn tạo ra).
/tools
Các công cụ hỗ trợ cho dự án này. Vui lòng lưu ý rằng các công cụ này có thể nhập mã từ các thư mục /pkg
và /internal
.
/examples
Ví dụ cho các ứng dụng và/hoặc thư viện công cộng.
/third_party
Các công cụ hỗ trợ bên ngoài, mã được chia nhánh và các công cụ tiện ích bên thứ ba khác (ví dụ, Swagger UI).
/githooks
Githooks.
/assets
Tài sản bổ sung (ảnh, logo, v.v.) được cung cấp với kho lưu trữ.
/website
Nơi lưu trữ dữ liệu trang web dự án nếu bạn không sử dụng GitHub Pages.
/src
Một số dự án Go có thể có thư mục src
, nhưng điều này thường do các nhà phát triển đến từ thế giới Java, nơi đó là một mẫu phổ biến. Nếu có thể, hãy cố gắng tránh áp dụng mẫu giống Java này. Bạn thực sự không muốn mã Go hoặc dự án của bạn trông giống như Java :-)
Đừng nhầm lẫn thư mục /src
ở mức dự án với thư mục /src
được sử dụng cho không gian làm việc Go, mô tả trong Cách viết mã Go
. Biến môi trường $GOPATH
trỏ vào không gian làm việc của bạn (hiện tại) (mặc định, trên hệ thống không phải Windows, nó trỏ vào thư mục $HOME/go
). Không gian làm việc này bao gồm các thư mục cấp cao /pkg
, /bin
, và /src
. Dự án thực tế của bạn sẽ là một thư mục con dưới thư mục /src
, vì vậy nếu dự án của bạn có một thư mục /src
, đường dẫn dự án sẽ trông như thế này: /some/path/to/workspace/src/your_project/src/your_code.go
. Vui lòng lưu ý rằng từ Go 1.11 trở đi, dự án của bạn có thể được đặt ngoài GOPATH
, nhưng điều đó không có nghĩa là sử dụng mẫu bố trí này là ý tưởng tốt.