Go Home Page
Die Programmiersprache Go

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.