Obwohl die akzeptierte Antwort immer noch richtig ist, wenn Verzeichnisse mit Paketnamen abgeglichen werden müssen, müssen Sie wirklich zur Verwendung von Go-Modulen migrieren, anstatt GOPATH zu verwenden. Neue Benutzer, die auf dieses Problem stoßen, sind möglicherweise verwirrt über die Erwähnungen der Verwendung von GOPATH (wie ich), die jetzt veraltet sind. Daher werde ich versuchen, dieses Problem zu beheben und Anleitungen zur Vermeidung dieses Problems bei der Verwendung von Go-Modulen bereitzustellen.
Wenn Sie bereits mit Go-Modulen vertraut sind und dieses Problem auftritt, fahren Sie mit meinen spezifischeren Abschnitten fort, in denen einige der Go-Konventionen behandelt werden, die leicht zu übersehen oder zu vergessen sind.
Dieses Handbuch enthält Informationen zu Go-Modulen: https://golang.org/doc/code.html
Projektorganisation mit Go-Modulen
Organisieren Sie nach der Migration zu Go-Modulen, wie in diesem Artikel erwähnt, den Projektcode wie folgt:
Ein Repository enthält ein oder mehrere Module. Ein Modul ist eine Sammlung verwandter Go-Pakete, die zusammen veröffentlicht werden. Ein Go-Repository enthält normalerweise nur ein Modul, das sich im Stammverzeichnis des Repositorys befindet. Eine Datei mit dem Namen go.mod deklariert dort den Modulpfad: das Importpfadpräfix für alle Pakete innerhalb des Moduls. Das Modul enthält die Pakete im Verzeichnis, das die Datei go.mod enthält, sowie die Unterverzeichnisse dieses Verzeichnisses bis zum nächsten Unterverzeichnis, das eine andere Datei go.mod enthält (falls vorhanden).
Der Pfad jedes Moduls dient nicht nur als Importpfadpräfix für seine Pakete, sondern gibt auch an, wo der Befehl go suchen soll, um es herunterzuladen. Um beispielsweise das Modul golang.org/x/tools herunterzuladen, konsultiert der Befehl go das unter https://golang.org/x/tools angegebene Repository (hier näher beschrieben).
Ein Importpfad ist eine Zeichenfolge, die zum Importieren eines Pakets verwendet wird. Der Importpfad eines Pakets ist sein Modulpfad, der mit seinem Unterverzeichnis innerhalb des Moduls verknüpft ist. Das Modul github.com/google/go-cmp enthält beispielsweise ein Paket im Verzeichnis cmp /. Der Importpfad dieses Pakets lautet github.com/google/go-cmp/cmp. Pakete in der Standardbibliothek haben kein Modulpfadpräfix.
Sie können Ihr Modul folgendermaßen initialisieren:
$ go mod init github.com/mitchell/foo-app
Ihr Code muss sich nicht auf github.com befinden, damit er erstellt werden kann. Es wird jedoch empfohlen, Ihre Module so zu strukturieren, als würden sie irgendwann veröffentlicht.
Verstehen, was passiert, wenn versucht wird, ein Paket zu erhalten
Es gibt hier einen großartigen Artikel, der darüber spricht, was passiert, wenn Sie versuchen, ein Paket oder Modul zu erhalten: https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16
Er beschreibt, wo das Paket gespeichert ist und wird helfen Ihnen zu verstehen, warum dieser Fehler möglicherweise auftritt, wenn Sie bereits Go-Module verwenden.
Stellen Sie sicher, dass die importierte Funktion exportiert wurde
Beachten Sie, dass Sie sicherstellen müssen, dass Sie Ihre Funktion exportiert haben, wenn Sie Probleme beim Zugriff auf eine Funktion aus einer anderen Datei haben. Wie im ersten Link beschrieben, muss eine Funktion mit einem Großbuchstaben beginnen, der exportiert und für den Import in andere Pakete verfügbar gemacht werden soll.
Namen von Verzeichnissen
Ein weiteres wichtiges Detail (wie in der akzeptierten Antwort erwähnt) ist, dass Namen von Verzeichnissen die Namen Ihrer Pakete definieren. (Ihre Paketnamen müssen mit ihren Verzeichnisnamen übereinstimmen.) Beispiele hierfür finden Sie hier: https://medium.com/rungo/everything-you-need-to-know-about-packages-in-go-b8bac62b74cc
With Die Datei mit Ihrer main
Methode (dh dem Einstiegspunkt Ihrer Anwendung) ist jedoch von dieser Anforderung ausgenommen.
Als Beispiel hatte ich Probleme mit meinen Importen, wenn ich eine Struktur wie diese verwendete:
/my-app
├── go.mod
├── /src
├── main.go
└── /utils
└── utils.go
Ich konnte den Code nicht utils
in mein main
Paket importieren .
Sobald ich jedoch main.go
ein eigenes Unterverzeichnis erstellt habe, wie unten gezeigt, funktionierten meine Importe einwandfrei:
/my-app
├── go.mod
├── /src
├── /app
| └── main.go
└── /utils
└── utils.go
In diesem Beispiel sieht meine go.mod-Datei folgendermaßen aus:
module git.mydomain.com/path/to/repo/my-app
go 1.14
Wenn ich main.go nach dem Hinzufügen eines Verweises auf gespeichert habe utils.MyFunction()
, hat meine IDE den Verweis auf mein Paket automatisch wie folgt abgerufen :
import "git.mydomain.com/path/to/repo/my-app/src/my-app"
(Ich verwende VS-Code mit der Golang-Erweiterung.)
Beachten Sie, dass der Importpfad das Unterverzeichnis zum Paket enthielt.
Umgang mit einem privaten Repo
Wenn der Code Teil eines privaten Repos ist, müssen Sie einen git-Befehl ausführen, um den Zugriff zu aktivieren. Andernfalls können andere Fehler auftreten. In diesem Artikel wird erwähnt, wie dies für private Github-, BitBucket- und GitLab-Repos durchgeführt wird: https://medium.com/cloud-native-the-gathering/go-modules-with-private-git- repositories-dfe795068db4
Dieses Problem wird auch hier behandelt: Wie kann man ein privates Repository richtig " abrufen "?