Menu

go mod init und Go-Module: go.mod, go get, go mod tidy

Wie Go-Module funktionieren: eins mit go mod init anlegen, einen Modulpfad wählen, Abhängigkeiten mit go get hinzufügen, mit go mod tidy aufräumen, wofür go.sum da ist und replace für die lokale Entwicklung.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Ein Modul ist ein Verzeichnisbaum aus Go-Paketen mit einer go.mod-Datei an der Wurzel. go.mod benennt das Modul und listet die Versionen aller anderen Module, von denen es abhängt. Du legst eins mit go mod init an:

mkdir myapp
cd myapp
go mod init example.com/myapp
go: creating new go.mod: module example.com/myapp

Die entstandene go.mod:

module example.com/myapp

go 1.24.5

Das reicht zum Bauen. Jedes Go-Projekt seit Go 1.16 ist ein Modul, und go build, go run . und go test verweigern ohne eins den Dienst:

go: go.mod file not found in current directory or any parent directory; see 'go help modules'

Einen Modulpfad wählen

Der Modulpfad ist das Präfix jedes Importpfads innerhalb des Moduls. Beim Modul example.com/myapp wird ein Paket im Verzeichnis internal/store als example.com/myapp/internal/store importiert.

SituationModulpfad
Code auf GitHub, den andere importieren könntengithub.com/yourname/project
Code deiner Firmayourcompany.com/project oder die URL des Repositorys
Ein privates Programm oder eine Übungexample.com/myapp oder einfach myapp
Version 2 oder höher eines veröffentlichten Modulsgithub.com/yourname/project/v2

Bei einer Bibliothek muss der Pfad dazu passen, wo der Code liegt, weil go get damit das Repository findet. Bei einem Programm, das nur du ausführst, ist der Pfad nur ein Name. Vermeide ein einzelnes Wort, das einem Paket der Standardbibliothek entspricht, etwa go mod init fmt oder go mod init strings: Der Build scheitert dann mit ambiguous import: found package fmt in multiple modules.

go mod init ohne Argument scheitert außerhalb des alten GOPATH-Layouts:

go: cannot determine module path for source directory /home/ana/myapp (outside GOPATH, module path must be specified)

Gib ihm einen Pfad.

Abhängigkeiten hinzufügen

Schreib den Import und lass Go das Paket holen. Angenommen, main.go importiert github.com/google/uuid. Ein Build, bevor das Modul davon weiß, liefert eine klare Anweisung:

main.go:6:2: no required module provides package github.com/google/uuid; to add it:
	go get github.com/google/uuid

Jeder der beiden Befehle behebt das:

go get github.com/google/uuid
# or, to sync go.mod with every import in the module:
go mod tidy

go get meldet, was es geändert hat:

go: downloading github.com/google/uuid v1.6.0
go: added github.com/google/uuid v1.6.0

go mod tidy meldet, wie es den Import aufgelöst hat:

go: finding module for package github.com/google/uuid
go: downloading github.com/google/uuid v1.6.0
go: found github.com/google/uuid in github.com/google/uuid v1.6.0

go.mod hat jetzt eine require-Zeile:

module example.com/myapp

go 1.24.5

require github.com/google/uuid v1.6.0

go get mit Versionen

BefehlWirkung
go get pkgpkg in der neuesten Release hinzufügen oder die aktuelle Version behalten, wenn es schon gefordert ist
go get pkg@v1.5.0genau v1.5.0 verwenden (Upgrade oder Downgrade)
go get pkg@latestauf die neueste Release wechseln
go get pkg@abc1234einen bestimmten Commit verwenden (als Pseudo-Version gespeichert)
go get -u ./...jede Abhängigkeit auf ihre neueste Minor- oder Patch-Release heben
go get -u=patch ./...nur auf die neuesten Patch-Releases heben
go get pkg@nonedie Anforderung entfernen
go get go@1.24die minimale Go-Version des Moduls anheben

go get ändert go.mod. Programme baut oder installiert es nicht mehr; seit Go 1.18 ist das die Aufgabe von go install pkg@version.

Indirekte Abhängigkeiten

Mit // indirect markierte Anforderungen sind Module, die dein Code nicht direkt importiert, die der Build aber braucht. Seit Go 1.17 listet go.mod jedes Modul, das dem Build ein Paket liefert, also tauchen die Abhängigkeiten deiner Abhängigkeiten hier mit dieser Markierung auf. go mod tidy verwaltet diese Markierungen; du fügst sie nicht selbst hinzu.

go mod tidy

Führ go mod tidy aus, wann immer du Imports hinzufügst oder entfernst. Es:

  • fügt Anforderungen für importierte Pakete hinzu, die fehlen,
  • entfernt Anforderungen, die nichts mehr importiert,
  • fügt die go.sum-Einträge hinzu, die der Build braucht, und entfernt veraltete.

Es betrachtet jedes Paket im Modul, einschließlich Tests und jeder Kombination von Build-Tags, und behält daher manchmal eine Abhängigkeit, deren Verwendung du auf deiner Plattform nicht siehst. go mod tidy vor jedem Commit auszuführen und in der CI zu prüfen, dass es keinen Diff erzeugt, hält go.mod ehrlich.

go.sum

go.sum speichert einen Hash für jede Modulversion, die der Build verwendet:

github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

Die erste Zeile hasht die Dateien des Moduls, die zweite nur seine go.mod. Lädt der Befehl go ein Modul herunter, prüft er den Hash gegen go.sum und gegen die öffentliche Checksummen-Datenbank (sum.golang.org), also lässt eine manipulierte oder still geänderte Release den Build scheitern. Committe go.sum neben go.mod und bearbeite es nie von Hand.

Wie Go Versionen auswählt

Go verwendet Minimal Version Selection. Jedes Modul listet die Mindestversion jeder Abhängigkeit, die es braucht, und der Build nimmt die höchste dieser Mindestversionen, nie etwas Neueres. Fordert dein Modul uuid v1.5.0 und eine Abhängigkeit uuid v1.6.0, nimmt der Build v1.6.0, auch wenn es v1.7.0 gibt. Nichts wird aktualisiert, außer jemand verlangt es mit go get.

Die Folge: Builds sind ohne Lockfile reproduzierbar. go.mod plus der Abhängigkeitsgraph bestimmen jede Version vollständig. go list -m all gibt das Ergebnis aus:

go list -m all
example.com/myapp
github.com/google/uuid v1.6.0

Major-Versionen

Ein Modul ab v2 muss die Major-Version in seinem Pfad tragen: github.com/yourname/project/v2. Der Importpfad ändert sich mit, also sind project und project/v2 verschiedene Module und können beide in einem Build vorkommen. Das ist die Regel von Go für inkompatible Änderungen, und deshalb siehst du Imports wie github.com/jackc/pgx/v5.

replace: an einer Abhängigkeit lokal arbeiten

Um Änderungen an einer Abhängigkeit zu testen, bevor du sie veröffentlichst, lenk ihren Pfad auf ein lokales Verzeichnis um:

module example.com/myapp

go 1.24.5

require example.com/mylib v1.2.0

replace example.com/mylib => ../mylib

Oder von der Kommandozeile:

go mod edit -replace example.com/mylib=../mylib
go mod tidy

Das Verzeichnis muss eine eigene go.mod enthalten. replace gilt nur, wenn dieses Modul direkt gebaut wird, nicht wenn jemand anderes davon abhängt. Denk also daran, es vor dem Taggen einer Release zu entfernen.

Um mehrere Module gleichzeitig zu bearbeiten, ohne ihre go.mod-Dateien anzufassen, hat Go 1.18 Workspaces eingeführt:

go work init . ../mylib

Das schreibt eine go.work-Datei, durch die das lokale mylib Vorrang bekommt. Halte go.work aus der Versionsverwaltung heraus, außer das ganze Team nutzt dasselbe Layout.

Tool-Abhängigkeiten (Go 1.24)

Go 1.24 hat die Direktive tool eingeführt, sodass Code-Generatoren und Linter in go.mod versioniert werden können, statt global installiert zu werden:

go get -tool golang.org/x/tools/cmd/stringer
go tool stringer -type=Color

func init ist etwas anderes

Suchen nach „golang init“ meinen oft die Funktion init, die mit go mod init nichts zu tun hat. Jedes Paket kann func init() deklarieren. Sie nimmt keine Argumente, kann von deinem Code nicht aufgerufen werden und läuft einmal automatisch, nachdem die Variablen auf Paketebene gesetzt sind und bevor main startet:

Eine Datei kann mehrere init-Funktionen haben, und sie laufen in der Reihenfolge, in der sie stehen. Importierte Pakete schließen ihre eigene Initialisierung zuerst ab. Halte init klein: Arbeit, die fehlschlagen kann, lässt sich als gewöhnliche Funktion, die du aus main aufrufst, leichter behandeln und testen.

Private Module und Proxys

Standardmäßig lädt go Module über proxy.golang.org herunter. Dieser Proxy sieht keine privaten Repositorys, also sag Go, welche Pfade privat sind:

go env -w GOPRIVATE=github.com/yourcompany/*

Module, die zu GOPRIVATE passen, werden direkt mit deinen Git-Zugangsdaten aus dem Repository geholt und umgehen die Checksummen-Datenbank.

Häufig gestellte Fragen

Was macht go mod init?

Es legt im aktuellen Verzeichnis eine go.mod-Datei an und macht dieses Verzeichnis damit zur Wurzel eines Moduls. go mod init example.com/myapp schreibt den Modulpfad und die Go-Version:

module example.com/myapp

go 1.24.5

Führ es einmal pro Projekt aus, vor go build oder go get.

Was sollte ich bei go mod init als Modulpfad verwenden?

Die Adresse, von der der Code geholt wird, wenn andere ihn importieren, meist den Pfad des Repositorys: go mod init github.com/yourname/project. Für ein Programm, das niemand importieren wird, funktioniert jeder Name (go mod init myapp), aber ein Pfad im Domain-Stil mit Punkt wie example.com/myapp vermeidet Kollisionen mit Paketnamen der Standardbibliothek.

Was ist der Unterschied zwischen go get und go mod tidy?

go get pkg@version fügt eine Abhängigkeit hinzu oder ändert ihre Version. go mod tidy liest deine Quelldateien, fügt jedes Modul hinzu, das deine Imports brauchen, das aber in go.mod fehlt, entfernt Anforderungen, die nichts importiert, und aktualisiert go.sum. Ein üblicher Ablauf: den Import schreiben, dann go mod tidy ausführen.

Sollte ich go.sum committen?

Ja. go.sum enthält kryptografische Hashes jeder Modulversion, die dein Build verwendet. Wenn du es committest, kann der Befehl go prüfen, dass alle byteidentische Abhängigkeiten herunterladen. Bearbeite es nie von Hand; go mod tidy pflegt es.

Ist „golang init“ dasselbe wie go mod init?

Nein, das sind verschiedene Dinge, die sich ein Wort teilen. go mod init ist ein Terminalbefehl, der go.mod anlegt. func init() ist eine Funktion, die du in Go-Code schreibst; sie läuft automatisch einmal vor main, nachdem die Variablen des Pakets initialisiert wurden.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S