Chociaż zaakceptowana odpowiedź jest nadal poprawna, jeśli chodzi o konieczność dopasowania katalogów do nazw pakietów, naprawdę musisz przejść do używania modułów Go zamiast używania GOPATH. Nowi użytkownicy, którzy napotkają ten problem, mogą być zdezorientowani wzmiankami o używaniu GOPATH (tak jak ja), które są teraz nieaktualne. Postaram się więc wyjaśnić ten problem i udzielić wskazówek związanych z zapobieganiem temu problemowi podczas korzystania z modułów Go.
Jeśli znasz już moduły Go i masz ten problem, przejdź do moich bardziej szczegółowych sekcji poniżej, które obejmują niektóre konwencje Go, które łatwo przeoczyć lub zapomnieć.
Ten przewodnik uczy o modułach Go: https://golang.org/doc/code.html
Organizacja projektu za pomocą modułów Go
Po migracji do modułów Go, jak wspomniano w tym artykule, zorganizuj kod projektu zgodnie z opisem:
Repozytorium zawiera co najmniej jeden moduł. Moduł to zbiór powiązanych pakietów Go, które są wydawane razem. Repozytorium Go zazwyczaj zawiera tylko jeden moduł znajdujący się w katalogu głównym repozytorium. Plik o nazwie go.mod deklaruje ścieżkę modułu: prefiks ścieżki importu dla wszystkich pakietów w module. Moduł zawiera pakiety w katalogu zawierającym jego plik go.mod, a także podkatalogi tego katalogu, aż do następnego podkatalogu zawierającego inny plik go.mod (jeśli istnieje).
Ścieżka każdego modułu nie tylko służy jako prefiks ścieżki importu dla jego pakietów, ale także wskazuje, gdzie polecenie go powinno szukać, aby go pobrać. Na przykład, aby pobrać moduł golang.org/x/tools, polecenie go skonsultuje się z repozytorium wskazanym przez https://golang.org/x/tools (opisane więcej tutaj).
Ścieżka importu to ciąg znaków używany do importowania pakietu. Ścieżka importu pakietu to ścieżka jego modułu połączona z podkatalogiem w module. Na przykład moduł github.com/google/go-cmp zawiera pakiet w katalogu cmp /. Ścieżka importu tego pakietu to github.com/google/go-cmp/cmp. Pakiety w bibliotece standardowej nie mają przedrostka ścieżki modułu.
Możesz zainicjować swój moduł w następujący sposób:
$ go mod init github.com/mitchell/foo-app
Twój kod nie musi znajdować się na github.com, aby mógł zostać zbudowany. Jednak najlepszą praktyką jest uporządkowanie modułów w taki sposób, jakby były ostatecznie publikowane.
Zrozumienie, co się dzieje podczas próby odebrania paczki
Jest tutaj świetny artykuł, który mówi o tym, co się dzieje, gdy próbujesz uzyskać pakiet lub moduł: https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16
Omawia, gdzie pakiet jest przechowywany i będzie pomoże Ci zrozumieć, dlaczego możesz otrzymać ten błąd, jeśli już używasz modułów Go.
Upewnij się, że zaimportowana funkcja została wyeksportowana
Zwróć uwagę, że jeśli masz problemy z dostępem do funkcji z innego pliku, musisz upewnić się, że funkcja została wyeksportowana. Jak opisano w pierwszym linku, który podałem, funkcja musi zaczynać się od dużej litery, aby można ją było wyeksportować i udostępnić do zaimportowania do innych pakietów.
Nazwy katalogów
Kolejnym krytycznym szczegółem (jak wspomniano w zaakceptowanej odpowiedzi) jest to, że nazwy katalogów definiują nazwy twoich pakietów. (Nazwy twoich pakietów muszą być zgodne z nazwami ich katalogów.) Możesz zobaczyć przykłady tutaj: https://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc
With To powiedziawszy, plik zawierający twoją main
metodę (tj. punkt wejścia twojej aplikacji) jest jakby zwolniony z tego wymogu.
Na przykład miałem problemy z importem, gdy korzystałem z takiej struktury:
/my-app
├── go.mod
├── /src
├── main.go
└── /utils
└── utils.go
Nie udało mi się zaimportować kodu utils
do mojego main
pakietu.
Jednak po umieszczeniu main.go
we własnym podkatalogu, jak pokazano poniżej, mój import działał dobrze:
/my-app
├── go.mod
├── /src
├── /app
| └── main.go
└── /utils
└── utils.go
W tym przykładzie mój plik go.mod wygląda następująco:
module git.mydomain.com/path/to/repo/my-app
go 1.14
Kiedy zapisałem main.go po dodaniu odwołania do utils.MyFunction()
, moje IDE automatycznie pobierało odwołanie do mojego pakietu w następujący sposób:
import "git.mydomain.com/path/to/repo/my-app/src/my-app"
(Używam VS Code z rozszerzeniem Golang).
Zwróć uwagę, że ścieżka importu zawierała podkatalog do pakietu.
Radzenie sobie z prywatnym repo
Jeśli kod jest częścią prywatnego repozytorium, musisz uruchomić polecenie git, aby umożliwić dostęp. W przeciwnym razie możesz napotkać inne błędy Ten artykuł wspomina, jak to zrobić w przypadku prywatnych repozytoriów Github, BitBucket i GitLab: https://medium.com/cloud-native-the-gathering/go-modules-with-private-git- repositories-dfe795068db4
Ten problem jest również omawiany tutaj: Jaki jest właściwy sposób na „zdobycie” prywatnego repozytorium?