Mặc dù câu trả lời được chấp nhận vẫn đúng về việc cần khớp các thư mục với tên gói, nhưng bạn thực sự cần phải chuyển sang sử dụng các mô-đun Go thay vì sử dụng GOPATH. Người dùng mới gặp phải vấn đề này có thể bị nhầm lẫn về các đề cập đến việc sử dụng GOPATH (như tôi), hiện đã lỗi thời. Vì vậy, tôi sẽ cố gắng làm rõ vấn đề này và cung cấp hướng dẫn liên quan đến việc ngăn chặn vấn đề này khi sử dụng các mô-đun Go.
Nếu bạn đã quen thuộc với các mô-đun Go và đang gặp phải vấn đề này, hãy bỏ qua các phần cụ thể hơn của tôi bên dưới, bao gồm một số quy ước về Go dễ bị bỏ qua hoặc quên.
Hướng dẫn này dạy về các mô-đun Go: https://golang.org/doc/code.html
Tổ chức dự án với các mô đun Go
Khi bạn di chuyển sang các mô-đun Go, như được đề cập trong bài viết đó, hãy tổ chức mã dự án như được mô tả:
Một kho chứa một hoặc nhiều mô-đun. Một mô-đun là một tập hợp các gói Go liên quan được phát hành cùng nhau. Kho lưu trữ Go thường chỉ chứa một mô-đun, nằm ở thư mục gốc của kho lưu trữ. Một tệp có tên go.mod ở đó khai báo đường dẫn mô-đun: tiền tố đường dẫn nhập cho tất cả các gói trong mô-đun. Mô-đun chứa các gói trong thư mục chứa tệp go.mod của nó cũng như các thư mục con của thư mục đó, cho đến thư mục con tiếp theo chứa tệp go.mod khác (nếu có).
Đường dẫn của mỗi mô-đun không chỉ đóng vai trò là tiền tố đường dẫn nhập cho các gói của nó mà còn cho biết lệnh go sẽ tìm ở đâu để tải xuống. Ví dụ: để tải xuống mô-đun golang.org/x/tools, lệnh go sẽ tham khảo kho lưu trữ được chỉ định bởi https://golang.org/x/tools (được mô tả thêm tại đây).
Đường dẫn nhập là một chuỗi được sử dụng để nhập gói. Đường dẫn nhập của gói là đường dẫn mô-đun được nối với thư mục con trong mô-đun. Ví dụ: mô-đun github.com/google/go-cmp chứa một gói trong thư mục cmp /. Đường dẫn nhập của gói đó là github.com/google/go-cmp/cmp. Các gói trong thư viện chuẩn không có tiền tố đường dẫn mô-đun.
Bạn có thể khởi tạo mô-đun của mình như thế này:
$ go mod init github.com/mitchell/foo-app
Mã của bạn không cần phải được đặt trên github.com để xây dựng mã. Tuy nhiên, đó là cách tốt nhất để cấu trúc các mô-đun của bạn như thể cuối cùng chúng sẽ được xuất bản.
Hiểu những gì xảy ra khi cố gắng để có được một gói
Có một bài viết tuyệt vời ở đây nói về những gì xảy ra khi bạn cố gắng nhận gói hoặc mô-đun: https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16
Nó thảo luận về nơi gói được lưu trữ và sẽ giúp bạn hiểu lý do tại sao bạn có thể gặp lỗi này nếu bạn đang sử dụng các mô-đun Go.
Đảm bảo chức năng đã nhập
Lưu ý rằng nếu bạn gặp sự cố khi truy cập một chức năng từ một tệp khác, bạn cần đảm bảo rằng bạn đã xuất khẩu chức năng của mình. Như được mô tả trong liên kết đầu tiên tôi cung cấp, một chức năng phải bắt đầu bằng một chữ cái viết hoa được xuất khẩu và có sẵn để nhập vào các gói khác.
Tên của thư mục
Một chi tiết quan trọng khác (như đã được đề cập trong câu trả lời được chấp nhận) là tên của các thư mục là những gì xác định tên của các gói của bạn. (Tên gói của bạn cần khớp với tên thư mục của chúng.) Bạn có thể xem các ví dụ về điều này tại đây: https://medium.com/rungo/everything-you-need-to-ledge-about-packages-in-go-b8bac62b74cc
Với có nghĩa là, tệp chứa main
phương thức của bạn (nghĩa là điểm vào của ứng dụng của bạn) là loại được miễn yêu cầu này.
Ví dụ, tôi gặp vấn đề với hàng nhập khẩu của mình khi sử dụng cấu trúc như thế này:
/my-app
├── go.mod
├── /src
├── main.go
└── /utils
└── utils.go
Tôi không thể nhập mã utils
vào main
gói của tôi .
Tuy nhiên, một khi tôi đưa main.go
vào thư mục con của riêng nó, như được hiển thị bên dưới, hàng nhập của tôi hoạt động tốt:
/my-app
├── go.mod
├── /src
├── /app
| └── main.go
└── /utils
└── utils.go
Trong ví dụ đó, tệp go.mod của tôi trông như thế này:
module git.mydomain.com/path/to/repo/my-app
go 1.14
Khi tôi đã lưu main.go sau khi thêm một tham chiếu vào utils.MyFunction()
, IDE của tôi sẽ tự động kéo tham chiếu vào gói của tôi như thế này:
import "git.mydomain.com/path/to/repo/my-app/src/my-app"
(Tôi đang sử dụng Mã VS với tiện ích mở rộng Golang.)
Lưu ý rằng đường dẫn nhập bao gồm thư mục con vào gói.
Xử lý một repo riêng
Nếu mã là một phần của repo riêng, bạn cần chạy lệnh git để cho phép truy cập. Mặt khác, bạn có thể gặp phải các lỗi khác Bài viết này đề cập đến cách thực hiện điều đó đối với các repos Github, BitBucket và GitLab riêng tư: https://medium.com/cloud-native-the-gathering/go-modules-with-private-git- kho lưu trữ-dfe795068db4
Vấn đề này cũng được thảo luận ở đây: cách thích hợp để "đi lấy" một kho lưu trữ riêng là gì?