How to Write Go Code — Deutsche Übersetzung
- Das Original:
-
https://golang.org/doc/code
Version of February 25, 2021 - Diese Übersetzung:
-
https://bitloeffel.de/DOC/golang/code_20210817_de.html
Stand: 04.08.2021
© 2020-21 Hans-Werner Heinzen @ Bitloeffel.de
Die Nutzung dieses Dokuments ist unter den Bedingungen der "Creative Commons Attribution 3.0"-Lizenz erlaubt. Für die verlinkten Quelldateien gelten andere Bestimmungen.
Für Fachbegriffe und ähnliches gibt es hier noch eine Wörterliste.
Wie man mit Go arbeitet
Einleitung
Dieses Dokument beschreibt die Entwicklung eines einfachen Go-Pakets innerhalb eines Moduls, und stellt das go-Kommando vor; das ist das Standard-Werkzeug zum Beschaffen, Umwandeln und Installieren von Go-Paketen und Programmen.
Hinweis: Dieses Dokument geht davon aus, dass Sie Go 1.13 oder neuer benutzen
und dass die Umgebungsvariable GO111MODULE
nicht gesetzt wurde.
Wenn Sie nach der älteren Prä-Modul-Version dieses Dokuments suchen:
das ist hier
(de) archiviert.
Kodeanordnung
Go-Programme werden als Pakete organisiert. Ein Paket ist eine Sammlung von Quelldateien im selben Verzeichnis, die zusammen umgewandelt werden. Funktionen, Typen, Variablen und Konstanten, die in einer Quelldatei definiert werden, sind auch allen anderen Quelldateien desselben Pakets bekannt.
Ein Depot (oder Repositorium) enthält ein oder mehrere Module.
Ein Modul ist eine Sammlung zusammengehöriger Go-Pakete, die
zusammen veröffentlicht/freigegeben werden. Ein Go-Depot enthält
normalerweise nur ein Modul, das sich an der Wurzel des Depots befindet.
Dort deklariert eine Datei go.mod
den Modulpfad;
das ist der Präfix der Importpfade für alle Pakete in diesem Modul.
Das Modul enthält die Pakete sowohl im Verzeichnis selbst, indem sich die
go.mod
-Datei befindet, als auch in dessen Unterverzeichnissen
bis hinunter zum ersten Unterverzeichnis, in dem sich eine andere
go.mod
-Datei befindet (wenn es eine solche gibt).
Beachten Sie, dass es zum Umwandeln nicht nötig ist, den Kode in einem entfernten Depot zu veröffentlichen. Ein Modul kann lokal definiert sein, ohne Teil eines Depot zu sein. Allerdings ist es guter Brauch, den Kode so anzuordnen, als ob Sie ihn eines Tages veröffentlichen wollten.
Der Modulpfad dient nicht nur als Präfix für die Importpfade seiner Pakete,
sondern zeigt dem Kommando go
auch, wo das Modul zum Kopieren
zu suchen ist. Ist beispielsweise ein Modul golang.org/x/tools
zu besorgen, so fragt das go
-Kommando bei einem Depot mit der
Bezeichnung https://golang.org/x/tools
nach.
(Genauer wird das hier beschrieben.)
Ein Importpfad ist eine Zeichenkette, die für das Importieren eines
Paket benutzt wird. Der Importpfad eines Pakets ist die Verkettung des
Modulpfads mit dem jeweiligen Unterverzeichnis innerhalb des Moduls.
Zum Beispiel enthält das Modul github.com/google/go-cmp
ein Paket im Unterverzeichnis cmp
. Der Importpfad dieses Pakets
ist dann github.com/google/go-cmp/cmp
. Pakete der
Standardbibliothek besitzen keinen Modulpfad als Präfix.
Ihr erstes Programm
Um ein einfaches Programm umzuwandeln und zu starten, wählen Sie zunächst
einen Modulpfad (wir benutzen hier example.com/user/hello
)
und erzeugen im Anschluss eine go.mod
-Datei, welche das Modul
deklariert:
$ mkdir hello # oder Sie klonen das bestehende Depot einer Versionsverwaltung $ cd hello $ go mod init example.com/user/hello go: creating new go.mod: module example.com/user/hello $ cat go.mod module example.com/user/hello go 1.16 $
Die erste Anweisung einer jeden Go-Quelldatei muss
package name
sein. Für ausführbare Kommandos muss
es immer package main
heißen.
Im oben angelegten Verzeichnis erzeugen Sie nun eine Datei namens
hello.go
, das den folgenden Go-Kode enthält:
package main import "fmt" func main() { fmt.Println("Hallo Welt") }
jetzt können Sie dieses Programm mit dem go
-Tool umwandeln
und installieren.
$ go install example.com/user/hello $
Dieses Kommando verfertigt das Kommando hello
,
produziert dabei eine ausführbare Binärdatei und installiert diese
als $HOME/go/bin/hello
(oder unter Windows
%USERPROFILE%\go\bin\hello.exe
).
Das Installationsverzeichnis wird durch die
Umgebungsvariablen
GOPATH
und GOBIN
bestimmt. Ist GOBIN
gesetzt, so werden Binärdateien dorthin installiert. Ist GOPATH
gesetzt, so werden Binärdateien in das bin
-Unterverzeichnis
des ersten Verzeichnisses in der GOPATH
-Liste installiert.
Trifft beides nicht zu, landen Binärdateien im
bin
-Unterverzeichnis des Standard-GOPATH
($HOME/go
oder %USERPROFILE%\go
).
Mit dem Kommando go env
können Sie (portierbar) den
Standardwert einer Umgebungsvariablen für künftige go
-Kommandos
setzen.
$ go env -w GOBIN=/somewhere/else/bin $
Zurücksetzen einer zuvor mit go env -w
gesetzten Variablen
geht mittels go env -u
:
$ go env -u GOBIN $
Kommandos wie go install
arbeiten im Kontext des Moduls,
in dem sich das aktuelle Arbeitsverzeichnis befindet. Liegt das aktuelle
Arbeitsverzeichnis nicht innerhalb des Moduls
example.com/user/hello
, so kann go install
scheitern.
Für eine bequemere Handhabung akzeptieren go
-Kommandos Pfade
relativ zum aktuellen Arbeitsverzeichnis; wenn kein anderer Pfad angegeben,
ist das aktuelle Arbeitsverzeichnis die Voreinstellung. Deshalb sind in
unserem Arbeitsverzeichnis die folgenden Kommandos gleichbedeutend:
$ go install example.com/user/hello
$ go install .
$ go install
Wir starten nun das Programm, um sicherzugehen, dass es auch fuktioniert.
Außerdem fügen wir das Installationsverzeichnis zur Variablen
PATH
hinzu, damit das Starten der Binärdateien eifacher wird:
# Windows-Anwender sollten unter https://github.com/golang/go/wiki/SettingGOPATH # nachsehen, wie man %PATH% setzt. $ export PATH=$PATH:$(dirname $(go list -f '{{"{{.Target}}"}}' .)) $ hello Hallo Welt $
Wenn Sie ein Versionskontrollsystem verwenden, wäre jetzt der richtige Zeitpunkt, ein Depot anzulegen (init), dort die Dateien anzumelden (add) und eine erste Änderung einzubuchen (commit). Aber nochmal, dieser Schritt ist optional; Sie brauchen kein Versionskontrollsystem, um mit Go zu arbeiten.
$ git init Initialized empty Git repository in /home/user/hello/.git/ $ git add go.mod hello.go $ git commit -m "Erster Commit" [master (root-commit) 0b4507d] initial commit 1 file changed, 7 insertion(+) create mode 100644 go.mod hello.go $
Das go
-Kommando lokalisiert das Depot zu einem vorgegebenen Modulpfad,
indem es über HTTPS bei der entsprechenden URL anfragt und die Metadaten aus der
HTML-Antwort extrahiert (siehe:
go help importpath
).
Viele Kodeherbergen bieten bereits Metadaten für Depots, die Go-Kode enthalten;
soll Ihr Modul also für andere erreichbar sein, ist es am einfachsten, wenn sein
Modulpfad der URL des Depots entspricht.
Import von Paketen Ihres Moduls
Wir programmieren nun ein Paket morestrings
und benutzen es in unserem
hello
-Programm. Erzeugen Sie als erstes ein Verzeichnis für das Paket
$HOME/hello/morestrings
und darin eine Datei namens
reverse.go
mit folgendem Inhalt:
// Paket morestrings enthält Funktionen zum Manipulieren von UTF-8-Zeichenketten, // die über das Angebot des Standardpakets "strings" hinausgehen. package morestrings // ReverseRunes gibt eine Zeichenkette zurück, bei dem die Reihenfolge der Runen // gegenüber dem Eingabeargument umgedreht wurde. func ReverseRunes(s string) string { r := []rune(s) for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] } return string(r) }
Weil unsere ReverseRunes
-Funktion mit einem Großbuchstaben beginnt,
wird sie exportiert und kann in
anderen Paketen benutzt werden, die unser morestrings
-Paket importieren.
Probieren wir mit go build
, ob das Paket erfolgreich umgewandelt wird:
$ cd $HOME/hello/morestrings $ go build $
Hier wird keine Ausgabedatei erzeugt. Stattdessen wird das kompilierte Paket in einem lokalen Zwischenspeicher (build cache) angelegt.
Wir wissen nun, dass morestrings
umgewandelt werden
kann — benutzen wir es also in unserem
hello
-Programm. Dazu ändern Sie bitte das
ursprüngliche $HOME/hello/hello.go
, so dass
morestrings
benutzt wird:
package main import ( "fmt" "example.com/user/hello/morestrings" ) func main() { fmt.Println(morestrings.ReverseRunes("!leseiZ rhi ,ollaH")) }
Installieren Sie das hello
-Programm:
$ go install example.com/user/hello
Nach Starten dieser neuen Programmversion sollten Sie die neue (umgedrehte) Nachricht sehen:
$ hello Hallo, ihr Ziesel!
Import von Paketen fremder Module
Ein Importpfad kann beschreiben, wie man zum Quellkode eines Pakets gelangt, auf
dem Weg über ein Versionkontrollsystem wie Git oder Mercurial. Das
go
-Kommando nutzt diese Eigenschaft, um Pakete automatisch von
entfernten Depots abzuholen, beispielsweise um
github.com/google/go-cmp/cmp
in Ihrem Programm zu benutzen:
package main import ( "fmt" "example.com/user/hello/morestrings" "github.com/google/go-cmp/cmp" ) func main() { fmt.Println(morestrings.ReverseRunes("!leseiZ rhi ,ollaH")) fmt.Println(cmp.Diff("Hallo Welt", "Hallo, ihr Ziesel!")) }
Da Sie jetzt von einem externen Modul abhängen, müssen Sie
diese entfernte Modul kopieren (download) und dessen Version
in der go.mod
-Datei festhalten. Das Kommando
go mod tidy
ergänzt fehlende Modulabhängigkeiten
für importierte Pakete und entfernt solche, die nicht mehr
hebraucht werden.
$ go mod tidy go: finding module for package github.com/google/go-cmp/cmp go: found github.com/google/go-cmp/cmp in github.com/google/go-cmp v0.5.4 $ go install example.com/user/hello $ hello Hallo, ihr Ziesel! string( - "Hallo Welt", + "Hallo, ihr Ziesel!", ) $ cat go.mod module example.com/user/hello go 1.16 require github.com/google/go-cmp v0.5.4 $
Voraussetzungen (Abhängigkeiten) von Modulen werden automatisch in das
pkg/mod
-Unterverzeichnis desjenigen Verzeichnisses kopiert, welches durch
die Umgebungsvariable GOPATH
bezeichnet wird. Die kopierten Inhalte
einer damit vorgegebenen Version eines Moduls werden von allen Modulen gemeinsam
genutzt, die diese Version erfordern (require
). Dazu markiert das
go
-Kommando betroffene Dateien und Verzeichnisse als schreibgeschützt.
Um alle fernkopierten Module zu löschen, können Sie dem Kommando
go clean
den Schalter -modcache
mitgeben:
$ go clean -modcache $
Testen
Go besitzt einen leichtgewichtigen Testrahmen, der aus dem Kommando
go test
und dem testing
-Paket besteht.
Sie schreiben einen Test, indem Sie eine Datei erstellen, deren Name in
_test.go
endet und die Funktionen namens TestXxx
mit der Signatur func (t *testing.T)
enthält.
Der Testrahmen aktiviert alle diese Funktionen; wenn eine dieser Funktionen eine
Fehlerfunktion, also etwa t.Error
oder t.Fail
, ruft,
so gilt der Test als fehlgeschlagen.
Fügen Sie dem morestrings
-Paket einen Test hinzu, indem Sie die Datei
$HOME/hello/morestrings/reverse_test.go
mit folgendem Go-Kode erzeugen:
package morestrings import "testing" func TestReverseRunes(t *testing.T) { cases := []struct { in, want string }{ {"Hello, world", "dlrow ,olleH"}, {"Hello, 世界", "界世 ,olleH"}, {"", ""}, } for _, c := range cases { got := ReverseRunes(c.in) if got != c.want { t.Errorf("ReverseRunes(%q) == %q, erwartet: %q", c.in, got, c.want) } } }
Starten Sie den test mit go test
:
$ go test PASS ok example.com/user/morestrings 0.165s $
Mehr über das Testen erfahren Sie, wenn Sie
go help test
starten, oder lesen Sie die Dokumentation des
testing
-Pakets
Wie weiter?
Melden Sie sich bei der Verteilerliste golang-announce an; Sie werden dann informiert, wenn eine neue stabile Go-Version freigegeben wird.
Lesen Sie in Effective Go (de), wie man klaren, typischen Go-Kode schreibt.
Machen sie A Tour of Go (de), um Go richtig kennenzulernen.
Besuchen Sie die Dokumentationsseite. Dort finden Sie in die Tiefe gehende Aufsätze über die Sprache Go, ihre Bibliotheken und ihre Werkzeuge.
Hilfe
Hilfe in Echtzeit erhalten Sie von hilfsbereiten Zieseln beim Gophers Slack Server (Eine Einladung können Sie hier bekommen).
Die offizielle Verteilerliste für Diskussionen zur Sprache Go ist Go Nuts.
Fehler melden Sie bitte über das Go-Fallbearbeitungssystem.