Go Home Page
Die Programmiersprache Go

How to Write Go Code — Deutsche Übersetzung

Das Original:
http://golang.org/doc/code.html
Version of January 6, 2017 (go1.8)
Diese Übersetzung:
http://www.bitloeffel.de/DOC/golang/code_20170216_de.html
Stand: 12.01.2017
© 2011-17 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, und stellt das go-Kommando vor; das ist das Standard-Werkzeug zum Beschaffen, Umwandeln und Installieren von Go-Paketen und Programmen.

Das go-Kommando verlangt, dass Sie Ihren Kode auf eine bestimmte Art anordnen. Lesen Sie diese Anleitung bitte sorgfältig: sie zeigt, wie Sie am schnellsten mit Ihrer Go-Installation in die Gänge kommen.

Eine ähnliche Anleitung gibt es auch als Bildergeschichte.

Kodeanordnung

Überblick

Beachten Sie, dass sich das von anderen Programmierumgebungen unterscheidet; dort hat normalerweise jedes Projekt einen eigenen Arbeitsbereich, und dieser ist eng mit dem Versionskontroll-Repositorium verknüpft.

Arbeitsbereiche

Ein Arbeitsbereich ist eine Ordnerhierarchie mit drei Ordnern an ihrer Basis:

Das go-Kommando wandelt Quellpakete um und installiert die erzeugten Binärdateien in den Ordnern pkg und bin.

Der Ordner src enthält typischerweise mehrere versionskontrollierte Repositorien (etwa für Git oder Mercurial), die die Versionsgeschichte eines oder mehrerer Pakete enthält.

Hier ein praktisches Beispiel für einen Arbeitsbereich:

bin/
    hello                          # ausführbares Kommando
    outyet                         # ausführbares Kommando
pkg/
    linux_amd64/
        github.com/golang/example/
            stringutil.a           # Paketobjekt
src/
    github.com/golang/example/
        .git/                      # Metadaten des Git-Repositoriums
        hello/
            hello.go               # Kommando-Quellkode
        outyet/
            main.go                # Kommando-Quellkode
            main_test.go           # Test-Quellkode
        stringutil/
            reverse.go             # Paket-Quellkode
            reverse_test.go        # Test-Quellkode
    golang.org/x/image/
        .git/                      # Metadaten des Git-Repositoriums
    bmp/
        reader.go                  # Paket-Quellkode
        writer.go                  # Paket-Quellkode
    ... (und noch viele weitere Repositorien und Pakete) ...

Der obige Baum zeigt einen Arbeitsbereich der die zwei Repositorien example und image enthält. Das example-Repositorium enthält zwei Kommandos (hello und outyet) sowie eine Bibliothek (stringutil). Das image-Repositorium enthält das Paket bmp und noch mehrere andere.

Ein typischer Arbeitsbereich besteht aus vielen Quellkode-Repositorien mit vielen Paketen und Kommandos. Die meisten Go-Programmierer halten ihren gesamten Go-Quellkode und allen Kode, von dem er abhängt in einem einzigen Arbeitsbereich.

Kommandos und Bibliotheken werden aus verschiedenen Arten von Quellpaketen erzeugt. Den Unterschied erörtern wir später.

Die Umgebungsvariable GOPATH

Die Umgebungsvariable GOPATH legt den Ort Ihres Arbeitsbereichs fest. Vorgabewert ist ein Verzeichnis go innerhalb Ihres Home-Verzeichnisses, also $HOME/go auf Unix, $home/go auf Plan 9 und %USERPROFILE%\go (üblicherweise C:\Users\YourName\go) auf Windows. Wenn Sie in einem anderen Verzeichnis arbeiten wollen, müssen Sie GOPATH so setzen, dass es auf dieses Verzeichnis zeigt. (Häufig wird auch GOPATH=$HOME gesetzt.) Achten Sie darauf, dass GOPATH nicht den Pfad zu Ihrer Go-Installation enthält.

Das Kommando go env GOPATH druckt den aktuell effektiven GOPATH; wurde die Umgebungsvariable nicht gesetzt, druckt es den Vorgabewert.

Damit's bequemer wird, fügen Sie das bin-Unterverzeichnis des Arbeitsbereichs zu Ihrer PATH-Variablen hinzu:

$ export PATH=$PATH:$(go env GOPATH)/bin

Die weiteren Skripte in diesem Dokument benutzen das kürzere $GOPATH anstelle von $(go env GOPATH). Wollen Sie diese Skripte benutzen aber haben GOPATH nicht gesetzt, können Sie entweder in den Kommandos alle $HOME/go ersetzen oder führen Sie das folgende Kommando durch:

$ export GOPATH=$(go env GOPATH)

Um mehr über die Umgebungsvariable GOPATH zu erfahren, benutzen Sie go help gopath.

Wollen Sie einen selbstdefinierten Arbeitsbereich nutzen, dann setzen Sie die GOPATH-Umgebungsvariable.

Importpfade

Ein Importpfad ist eine Zeichenkette, die ein Paket eindeutig bestimmt. Der Importpfad eines Pakets entspricht seiner Stellung innerhalb eines Arbeitsbereichs oder innerhalb eines fernen Repositoriums. (Das wird weiter unten erklärt.)

Die Pakete der Standardbibliothek haben kurze Importnamen bekommen, wie z.B. "fmt" oder "net/http". Für Ihr eigenes Projekt wählen Sie bitte einen Namen, der wahrscheinlich nicht mit zukünftigen Standardpaketen oder anderen, externen Bibliotheken kollidieren wird.

Wenn Sie Ihren Kode irgendwo in einem Repositorium lagern, dann sollten Sie die Wurzel dieses Repositoriums als Basis-Pfad benutzen. Angenommen Sie haben ein Konto bei GitHub unter github.com/user, dann soll das auch Ihr Basis-Pfad sein.

Hinweis: Sie müssen Ihren Kode nicht in einem fernen Repositorium veröffentlichen. Es ist nur gute Praxis, den Quellkode so zu organisieren, als ob er eines Tages veröffentlicht werden würde. Sie können aber jeden beliebigen Pfadnamen wählen, solange er bezogen auf die Standardbibliothek und das darüber hinausgehende Go-Ökosystem eindeutig ist.

Wir wählen hier github.com/user als Basis-Pfad. Erzeugen Sie für Ihren Quellkode einen Ordner in Ihrem Arbeitsbereich:

$ mkdir -p $GOPATH/src/github.com/user

Ihr erstes Programm

Zum Entwickeln eines simplen Programms wählen Sie zuerst einen Importpfad (wir wählen github.com/user/hallo) und erzeugen Sie ein entsprechendes Paketverzeichnis innerhalb Ihres Arbeitsbereichs:

$ mkdir $GOPATH/src/github.com/user/hallo

Als nächstes legen Sie dort eine Datei namens hallo.go an, die folgenden Go-Kode enthält:

package main

import "fmt"

func main() {
    fmt.Printf("Hallo, ihr Ziesel.\n")
}

Jetzt kompilieren Sie das Programm und installieren es mit dem go-Kommando:

$ go install github.com/user/hallo

Sie können dieses Kommando von irgendwo auf Ihrem System aus starten. Das go-Kommando findet den Quellkode, indem es nach dem github.com/user/hallo-Paket innerhalb Ihres durch GOPATH festgelegten Arbeitsbereichs sucht.

Sie können aber auch auf den Importpfad verzichten, indem Sie go install direkt aus dem Paketverzeichnis aufrufen:

$ cd $GOPATH/src/github.com/user/hallo
$ go install

Dieses Kommando kompiliert das hallo-Kommando und erzeugt eine ausführbare Binärdatei. Es installiert dann diese Binärdatei mit dem Namen hallo (oder unter Windows, hallo.exe) im bin-Unterordner des Arbeitsbereichs. Für unser Beispiel heißt das $GOPATH/bin/hallo, also $HOME/work/bin/hallo.

Output erzeugt das go-Kommando nur, wenn ein Fehler auftritt; wenn also nichts ausgegeben wurde, dann war das Kommando erfolgreich.

Jetzt können Sie das Programm starten, indem Sie den vollständigen Pfadnamen in die Kommandozeile eingeben:

$ $GOPATH/bin/hallo
Hallo, ihr Ziesel.

Wenn Sie schon $GOPATH/bin an Ihr PATH angehängt haben, dann tippen Sie nur den Namen der Binärdatei:

$ hallo
Hallo, ihr Ziesel.

Wenn Sie mit automatischer Versionskontrolle arbeiten, wäre jetzt der geeignete Zeitpunkt, ein Repositorium anzulegen, die Datei anzumelden und die erste Änderung einzubuchen. Aber nochmal, dieser Schritt ist optional; Sie brauchen keine Versionskontrolle um mit Go arbeiten zu können.

$ cd $GOPATH/src/github.com/user/hallo
$ git init
Initialized empty Git repository in /home/user/work/src/github.com/user/hallo/.git/
$ git add hallo.go
$ git commit -m "initial commit"
[master (root-commit) 0b4507d] initial commit
 1 file changed, 1 insertion(+)
  create mode 100644 hallo.go

Den Kode jetzt noch in einem entfernten Repositorium zu sichern, bleibt dem Leser als Übung überlassen.

Ihre erste Bibliothek

Schreiben wir nun eine Bibliothek, die wir im hallo-Programm benutzen wollen.

Die ersten Schritte sind wiederum, einen Importpfad festzulegen (wir wählen github.com/user/stringutil) sowie einen Paketordner anzulegen:

$ mkdir $GOPATH/src/github.com/user/stringutil

Als nächstes legen Sie dort eine Datei namens reverse.go an, die folgenden Go-Kode enthält:

// Paket stringutil enthält Hilfsfunktionen zum Bearbeiten von Strings.
package stringutil

// Reverse gibt den Argument-String umgedreht (Runenweise von rechts nach links) zurück.
func Reverse(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)
}

Testen Sie jetzt das Paket mit go build:

$ go build github.com/user/stringutil

Oder, wenn Sie im Quellverzeichnis des Pakets arbeiten:

$ go build

Es wird keine Ausgabedatei erzeugt. Um das zu erreichen, müssten Sie go install benutzen, wodurch das Paket-Objekt innerhalb des pkg-Unterordner des Arbeitsbereiches abgelegt würde.

Nachdem Sie sich überzeugt haben, dass das Paket stringutil sich umwandeln lässt, modifizieren Sie Ihr ursprüngliches hallo.go (das sich in $GOPATH/src/github.com/user/hallo befindet), um dort stringutil zu benutzen:

package main

import (
    "fmt"
    "github.com/user/stringutil"
)

func main() {
	fmt.Printf(stringutil.Reverse(".leseiZ rhi ,ollaH"))
}

Immer, wenn das go-Kommando ein Paket oder eine Binärdatei installiert, installiert es auch alles, wovon diese abhängen. Also, wenn Sie jetzt das Programm hallo installieren mit:

$ go install github.com/user/hallo

dann wird das stringutil-Paket gleich mit installiert.

Mit Ausführen der neuen Programmversion sollten Sie die neue umgekehrte Meldung:

$ hallo
Hallo, ihr Ziesel.

sehen. Und Ihr Arbeitsbereich sollte inzwischen so aussehen:

bin/
    hallo                 # ausführbares Kommando
pkg/
    linux_amd64/          # entspricht Ihrem Betriebssystem und der Rechnerarchitektur
        github.com/user/
            stringutil.a  # Paket-Objekt
src/
    github.com/user/
        hallo/
            hallo.go      # Kommando-Quelle
        stringutil/
            reverse.go    # Paket-Quelle

Beachten Sie, dass go install das stringutil.a-Objekt in einem Verzeichnis unterhalb von pkg/linux_amd64 abgelegt hat, welches dem Quellverzeichnis entspricht. Das ist deshalb so, damit spätere Aufrufe des go-Kommandos das Paket-Objekt finden, womit die überflüssige erneute Umwandlung vermieden wird. Der Teil linux_amd64 dient der plattformübergreifenden Kompilation und entspricht dem Betriebssystem und der Architektur Ihres Systems.

In Go werden ausführbare Kommandos statisch gebunden; für die Ausführung selbst werden die Paketobjekte nicht mehr gebraucht.

Paketnamen

Die erste Anweisung in einer Go-Quelldatei lautet:

package name

name ist der Standardname des Pakets fürs Importieren. (Alle Dateien eines Pakets müssen denselben Namen benutzen.)

Eine Go-Konvention besagt, dass der Paketname gleich dem letzten Teil des Importpfads ist: ein Paket, das als "crypto/rot13" importiert wird, sollte auch rot13 heißen.

Ausführbare Kommandos müssen immer package main benutzen.

Paketnamen müssen nicht eindeutig sein; für alle Pakete, die in einer Binärdatei zusammengebunden werden, müssen nur ihre Import-Pfade (also ihre qualifizierten Namen) eindeutig sein.

Mehr über Namenskonventionen in Go erfahren Sie in Effective Go [de].

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 jede dieser Funktionen; wenn eine solche Funktion eine Fehlerfunktion, etwa t.Error oder t.Fail ruft, so gilt der Test als fehlgeschlagen.

Fügen Sie nun dem stringutil-Paket einen Test hinzu, indem Sie eine Datei namens $GOPATH/src/github.com/user/stringutil/reverse_test.go anlegen, die folgenden Kode enthält:

package stringutil

import "testing"

func TestReverse(t *testing.T) {
    cases := []struct {
        in, want string
    }{
        {"Hello, world", "dlrow ,olleH"},
        {"Hello, 世界", "界世 ,olleH"},
        {"", ""},
    }
    for _, c := range cases {
        got := Reverse(c.in)
        if got != c.want {
            t.Errorf("Reverse(%q) == %q, erwartet wurde %q", c.in, got, c.want)
        }
    }
}

Starten Sie diesen Test mit go test:

$ go test github.com/user/stringutil
ok  	github.com/user/stringutil 0.165s

Und wie immer, wenn Sie das go-Kommando aus dem Paket-Ordner heraus aufrufen, können Sie den Importpfad weglassen:

$ go test
ok  	github.com/user/stringutil 0.165s

Weitere Details erfahren Sie, wenn Sie go help test eingeben, und aus der Dokumentation des testing-Pakets.

Ferne Pakete

Ein Import-Pfadname kann festlegen, wie man Paket-Quellkode von einem Versionskontrollsystem wie Git oder Mercurial bekommt. Das go-Kommando benutzt das, um automatisch Pakete von entfernten Repositorien abzuholen. Die in diesem Aufsatz beschriebenen Beispiele etwa sind in einem Git-Repositorium bei github.com/golang/example hinterlegt. Wenn Sie die URL des Repositoriums im Import-Pfadnamen des Pakets mit angeben, so wird go get es automatisch abholen, umwandeln und installieren:

$ go get github.com/golang/example/hello
$ $GOPATH/bin/hello
Hello, Go examples!

Befindet sich das gewünschte Paket nicht in einem Arbeitsbereich, so platziert go get es im ersten Arbeitsbereich, den GOPATH nennt. (Existiert das Paket bereits, so überspringt go get das Abholen, und verhält sich ansonsten so wie go install.)

Im Anschluss an das obige go get-Kommando, sollte Ihr Arbeitsbereich so aussehen:

bin/
    hallo                           # ausführbares Kommando
    hello                           # ausführbares Kommando
pkg/
    linux_amd64/
        github.com/golang/example/
            stringutil.a            # Paket-Objekt
        github.com/user/
            stringutil.a            # Paket-Objekt
src/
    github.com/golang/example/
        .git/                       # Metadaten des Git-Repositoriums
        hello/
            hello.go                # Kommando-Quelle
        stringutil/
            reverse.go              # Paket-Quelle
            reverse_test.go         # Test-Quelle
    github.com/user/
        hallo/
            hallo.go                # Kommando-Quelle
        stringutil/
            reverse.go              # Paket-Quelle
            reverse_test.go         # Test-Quelle

Das hello-Kommando, das bei Github hinterlegt ist, hängt vom Paket stringutil im selben Repositorium ab. Die Imports in der Datei hello.go halten sich an unsere Konvention für Import-Pfade, so dass das Kommando go get in der Lage ist, das benötigte Paket ebenfalls zu lokalisieren und zu installieren.

import "github.com/golang/example/stringutil"

Einhalten dieser Konvention ist der einfachste Weg, anderen Ihr Go-Paket zugänglich zu machen. Das Go-Wiki sowie godoc.org halten Listen von externen Go-Projekten bereit.

Für weitere Informationen zum Benutzen von fernen Repositorien mit dem go-Kommando, siehe: go help importpath.

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, wenn Sie die hilfsbereiten Ziesel bei #go-nuts auf dem Freenode-IRC-Server fragen.

Die offizielle Verteilerliste für Diskussionen zur Sprache Go ist Go Nuts.

Fehler melden Sie bitte über das Go-Fallbearbeitungssystem.