Kapitel 1. Erste Schritte Rezepte

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

1.0 Einleitung

fangen wir ganz einfach an. In diesem Kapitel lernst du die wichtigsten Rezepte, um mit der Programmierung in Go zu beginnen, Go zu installieren und dann einfachen Go-Code zu schreiben. Du lernst die Grundlagen kennen, von der Verwendung externer Bibliotheken und der Fehlerbehandlung bis hin zu einfachen Tests und der Protokollierung von Ereignissen. Einige dieser Rezepte sind absichtlich kurz gehalten - mehr Details dazu findest du in späteren Kapiteln. Wenn du bereits mit den Grundlagen von Go vertraut bist, kannst du dieses Kapitel ganz überspringen.

1.1 Installation von Go

Problem

Du möchtest Go installieren und die Umgebung für die Go-Entwicklung vorbereiten.

Lösung

Gehe auf die Go-Website und lade die neueste und beste Version von Go herunter. Befolge dann die Installationsanweisungen, um Go zu installieren.

Diskussion

Zuerst musst du auf die Go-Downloadseite gehen. Dort kannst du die richtige Version für dein Betriebssystem und deine Hardware auswählen und das richtige Paket herunterladen.

Es gibt mehrere Möglichkeiten, Go zu installieren: Du kannst entweder die vorgefertigten Binärdateien für deine Plattform installieren oder es aus dem Quellcode kompilieren. In den meisten Fällen ist es nicht nötig, Go aus dem Quellcode zu kompilieren, es sei denn, du findest keine passenden vorgefertigten Binärdateien für dein Betriebssystem. Auch dann kannst du Go normalerweise mit dem Paketmanager deines Betriebssystems installieren.

MacOS

Öffne die heruntergeladene Paketdatei und folge den Eingabeaufforderungen zur Installation. Go wird unter /usr/local/go installiert, und deine Umgebungsvariable PATH sollte auch /usr/local/go/bin enthalten.

Du kannst auch Homebrew für die Installation verwenden, das normalerweise ein oder zwei Versionen hinterherhinkt. Führe dazu den folgenden Befehl in der Kommandozeile aus:

$ brew update && brew install golang

Du kannst die PATH später nach Belieben einrichten.

Linux

Entpacke die heruntergeladene Archivdatei nach /usr/local, wodurch ein go Verzeichnis entstehen sollte. Führe z.B. diese Datei von der Kommandozeile aus (ersetze die Go-Version nach Bedarf):

$ rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.1.linux-amd64.tar.gz

Du kannst /usr/local/go/bin nach Bedarf in dein PATH einfügen, indem du diese Zeile in dein $HOME/.profile einfügst:

export PATH=$PATH:/usr/local/go/bin

Die Änderungen werden beim nächsten Einloggen vorgenommen. Wenn du möchtest, dass sie sofort wirksam werden, rufe source für deine Profildatei auf:

$ source $HOME/.profile

Windows

Öffne die heruntergeladene MSI-Installationsdatei und folge den Eingabeaufforderungen, um Go zu installieren. Standardmäßig wird Go unter Program Files oder Program Files (x86) installiert, aber du kannst dies jederzeit ändern.

Aus der Quelle bauen

Du solltest nicht vom Quellcode bauen, es sei denn, du kannst die vorgefertigten Binärdateien für dein Betriebssystem nicht finden. Wenn du es dennoch tun musst, entpacke die Quelldateien zunächst in ein geeignetes Verzeichnis und führe dann diese Befehle von der Kommandozeile aus:

$ cd src
$ ./all.bash

Wenn du unter Windows entwickelst, verwende stattdessen all.bat. Wir gehen hier davon aus, dass die Compiler bereits installiert sind. Wenn nicht und wenn du dich eingehender mit der Installation von Go befassen möchtest, findest du auf der Seite Go installieren weitere Informationen.

Wenn alles gut geht, solltest du etwas wie das hier sehen:

ALL TESTS PASSED

---
Installed Go for linux/amd64 in /home/you/go.
Installed commands in /home/you/go/bin.
*** You need to add /home/you/go/bin to your $PATH. ***

Um zu überprüfen, ob du Go installiert hast, kannst du das Go-Tool mit der Option version ausführen, um die installierte Version zu sehen:

% go version

Wenn du Go richtig installiert hast, solltest du etwas wie das hier sehen:

go version go1.20.1 darwin/amd64

1.2 Herumspielen mit Go

Problem

Du möchtest Go-Code schreiben und ausführen, ohne Go herunterzuladen und zu installieren.

Lösung

Verwende den Go Playground, um deinen Go-Code auszuführen.

Diskussion

Der Go Playground läuft auf den Servern von Google, und du kannst dein Programm in einer Sandbox ausführen. Rufe die Go Playground URL in deinem Browser auf. In dieser Online-Umgebung kannst du mit Go-Code spielen und die neueste Go-Version ausführen (du kannst zu einer anderen Version wechseln). Dieselbe Webseite gibt auch Ausgaben zurück, unterstützt aber nur Standardausgabe und Standardfehler (siehe Abbildung 1-1).

In der Not ist der Go Playground eine gute Option, um Go-Code zu testen. Du kannst den Go Playground auch nutzen, um ausführbaren Code direkt zu teilen.

The Go Playground
Abbildung 1-1. Go Spielplatz

1.3 Ein Hallo-Welt-Programm schreiben

Problem

Du möchtest ein einfaches Hello World-Programm in Go erstellen.

Lösung

Schreibe den Hello World-Code in Go, erstelle ihn und führe ihn aus.

Diskussion

Hier ist ein einfaches Hello World-Programm. Lege es in einer Datei namens hello.go in einem Verzeichnis namens hello ab:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

Die erste Zeile definiert das Paket, in dem dieser Code läuft. Funktionen werden in Paketen gruppiert und Codedateien in denselben Paketen befinden sich alle im selben Verzeichnis. Das Paket main ist besonders, weil es Go mitteilt, dass es als ausführbares Programm kompiliert werden soll. Wir importieren auch das Paket fmt, das Teil der Standardbibliothek ist.

Das main Paket muss eine main Funktion haben, mit der die Ausführung des Programms beginnt. Im Körper der Funktion main verwenden wir die Funktion Println aus dem Paket fmt, um die Zeichenkette "Hello, World!" auszugeben. Das Paket fmt ist Teil der Go-Standardbibliothek. Go hat eine ziemlich gute Standardbibliothek, die das meiste abdeckt, was du normalerweise brauchst. Besuche Go's Standardbibliothek, um herauszufinden, was die Standardbibliothek enthält.

Du kannst dieses Programm sofort ausführen, indem du es über die Befehlszeile startest:

$ go run hello.go

Du solltest dies auf deinem Bildschirm sehen:

Hello, World!

Du kannst sie auch in eine ausführbare Datei kompilieren, indem du diesen Befehl ausführst:

$ go build

Dadurch wird eine ausführbare Datei mit dem Namen hello (macOS oder Linux) oder hello.exe(Windows) im selben Verzeichnis erstellt. Der Name hello folgt auf den Namen des Verzeichnisses, in dem sie sich befindet. Du kannst den Ausgabenamen mit diesem Befehl ändern:

$ go build -o helloworld

Dadurch wird eine ausführbare Datei mit dem Namen helloworld (macOS oder Linux) oderhelloworld.exe (Windows) erstellt.

1.4 Ein externes Paket verwenden

Problem

Du möchtest ein Paket aus einer externen Bibliothek importieren.

Lösung

Verwende das Schlüsselwort import, um ein externes Paket zu importieren.

Diskussion

Nehmen wir an, du willst die Größe einer Datei anzeigen. Du erhältst die genaue Dateigröße, aber es ist eine relativ große Zahl, die für die Benutzer nicht intuitiv ist. Du möchtest die Dateigröße einfach anzeigen, ohne selbst viel rechnen zu müssen.

Du hast das Internet durchsucht und dieses interessante Open-Source-Paket von einem Drittanbieter unter https://github.com/dustin/go-humanize gefunden, das alles kann, was du willst. Wie kannst du es einbinden und die Funktionen des Pakets nutzen?

Du kannst das genauso machen wie das Importieren einer Standardbibliothek, aber statt des Paketnamens verwendest du den Paketort. Normalerweise würdest du erwarten, dass der Name des Pakets go-humanize lautet. Der im Code selbst verwendete Paketname lautet jedoch humanize. Das liegt daran, dass der Paketname, wie er vom Autor dieses Pakets definiert wurde, humanize lautet:

package main

import (
	"fmt"

	"github.com/dustin/go-humanize"
)

func main() {
	var number uint64 = 123456789
	fmt.Println("Size of file is", humanize.Bytes(number))
}

In vielen Fällen ist das letzte Verzeichnis des Speicherorts der Name des Pakets, aber das muss nicht immer so sein. Du kannst sogar die Art und Weise ändern, wie du Funktionen im externen Paket aufrufst:

package main

import (
	"fmt"

	human "github.com/dustin/go-humanize"
)

func main() {
	var number uint64 = 123456789
	fmt.Println("Size of file is", human.Bytes(number))
}

Beachte, dass du jetzt den Namen human verwendest, wenn du die Funktionen aufrufst. Warum lässt Go das zu? Weil es widersprüchliche Paketnamen geben könnte, da Go weder kontrolliert, wie die Pakete benannt werden, noch über ein zentrales Repository für Pakete verfügt.

Wenn du versuchst, dies direkt auszuführen, nehmen wir an, dass sich der Quellcode in einer Datei namens human.go befindet:

$ go run human.go

wirst du diese Fehlermeldung sehen:

human.go:6:2: no required module provides package github.com/dustin/go-humanize:
go.mod file not found in the current directory or any parent directory; see
'go help modules'

Das liegt daran, dass Go nicht weiß, wo es das Paket eines Drittanbieters finden kann (im Gegensatz zu den Paketen der Standardbibliothek); du musst es ihm mitteilen. Dazu musst du zunächst ein Go-Modul erstellen:

$ go mod init github.com/sausheong/humanize

Dadurch wird ein Go-Modul mit dem Modulpfad github.com/sausheong/humanize erstellt, der in einer go.mod-Datei angegeben ist. Diese Datei versorgt Go mit Informationen über die verschiedenen Pakete von Drittanbietern, die eingebunden werden sollen. Anschließend kannst du das Paket go-humanize wieder über das Tool go beziehen:

$ go get github.com/dustin/go-humanize

Dadurch wird das Drittanbieterpaket zum Modul hinzugefügt. Zum Aufräumen kannst du Folgendes ausführen:

$ go mod tidy

Damit wird die Datei go.mod aufgeräumt. Zu den Go-Modulen kommst du in Kapitel 2 zurück.

1.5 Umgang mit Fehlern

Problem

Du willst dich um Fehler kümmern, die unweigerlich auftreten, weil die Dinge nie wie erwartet ablaufen.

Lösung

Prüfe, ob eine Funktion einen Fehler zurückgibt und behandle ihn entsprechend.

Diskussion

Die Fehlerbehandlung in Go ist wichtig. Go ist so konzipiert, dass du explizit auf Fehler prüfen musst. Funktionen, die einen Fehler machen könnten, geben einen eingebauten Typ namens error zurück.

Funktionen, die eine Zeichenkette in eine Zahl umwandeln (wie ParseFloat und ParseInt), können in Schwierigkeiten geraten, weil die Zeichenkette möglicherweise keine Zahl ist und daher immer einen Fehler zurückgibt. Im Paket strconv zum Beispiel geben Funktionen, die eine Zahl in eine Zeichenkette umwandeln (wie FormatFloat und FormatInt), keine Fehler zurück. Das liegt daran, dass du gezwungen bist, eine Zahl einzugeben, und dass alles, was du eingibst, in eine Zeichenkette umgewandelt wird.

Sieh dir den folgenden Code an:

func main() {
	str := "123456789"
	num, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		panic(err)
	}
	fmt.Println("Number is", num)
}

Die Funktion ParseInt nimmt einen String (und einige andere Parameter) auf und gibt eine Zahl num und einen Fehler err zurück. Du solltest die err überprüfen, um zu sehen, ob die Funktion ParseInt etwas zurückgibt. Wenn es einen Fehler gibt, kannst du ihn so behandeln, wie du willst. In diesem Beispiel gibst du panic ein, wodurch das Programm beendet wird.

Wenn alles gut geht, solltest du das hier sehen:

Number is 123456789

Wenn du str in "abcdefg" änderst, erhältst du dies:

panic: strconv.ParseInt: parsing "abcdefghi": invalid syntax

goroutine 1 [running]:
main.main()
	/Users/sausheong/work/src/github.com/sausheong/gocookbook/ch01_general/
	main.go
	+0xae
exit status 2

Natürlich kannst du sie anders behandeln oder sogar ignorieren, wenn du willst. Du wirst dich in Kapitel 3 eingehend mit der Fehlerbehandlung befassen.

1.6 Ereignisse protokollieren

Problem

Du willst Ereignisse aufzeichnen, die während der Ausführung deines Codes passieren.

Lösung

Verwende das log Paket in der Go Standardbibliothek, um Ereignisse zu protokollieren.

Diskussion

Die Protokollierung von Ereignissen während der Codeausführung gibt dir einen guten Überblick darüber, wie sich der Code während der Ausführung verhält. Das ist wichtig, vor allem bei lang laufenden Programmen. Logs helfen dabei, Probleme bei der Ausführung und den Status der Ausführung zu ermitteln. Hier ist ein einfaches Beispiel von vorhin:

package main

import (
	"fmt"
	"log"
	"strconv"
)

func main() {
	str := "abcdefghi"
	num, err := strconv.ParseInt(str, 10, 64)
	if err != nil {
		log.Fatalln("Cannot parse string:", err)
	}
	fmt.Println("Number is", num)
}

Wenn beim Aufruf der Funktion strconv.ParseInt ein Fehler zurückgegeben wird, rufst du log.Fatalln auf, was gleichbedeutend mit der Protokollierung der Ausgabe auf dem Bildschirm und dem Beenden der Anwendung ist. Wie du siehst, werden bei der Protokollierung auf dem Bildschirm auch das Datum und die Uhrzeit des Ereignisses hinzugefügt:

021/11/18 09:19:35 Cannot parse string: strconv.ParseInt: parsing "abcdefghi":
invalid syntax
exit status 1

Standardmäßig geht das Protokoll an den Standardausgang, d.h. es wird auf dem Terminalbildschirm ausgegeben. Du kannst es aber ganz einfach in eine Datei oder sogar in mehrere Dateien umwandeln. Mehr dazu in Kapitel 4.

1.7 Testen deines Codes

Problem

Du willst die Funktionalität deines Codes testen, um sicherzustellen, dass er so funktioniert, wie du es willst.

Lösung

Verwende das in Go integrierte Testwerkzeug, um Funktionstests durchzuführen.

Diskussion

Go hat ein nützliches eingebautes Testwerkzeug, das das Testen einfacher macht, da du keine weitere Bibliothek eines Drittanbieters hinzufügen musst. Du wandelst den bisherigen Code in eine Funktion um und lässt deine main Funktion frei:

func main() {
}

func conv(str string) (num int64, err error) {
	num, err = strconv.ParseInt(str, 10, 64)
	return
}

Du wirst einige Tests mit dieser Funktion durchführen. Dazu erstellst du eine Datei, die mit _test.go endet, im selben Verzeichnis. In diesem Fall erstellst du eine Datei conv_test.go.

In diese Datei kannst du die verschiedenen Testfälle schreiben, die du möchtest. Jeder Testfall kann einer Funktion entsprechen, die mit Test beginnt und einen einzelnen Parameter vom Typ testing.T aufnimmt.

Du kannst so viele Testfälle hinzufügen, wie du willst, solange sie alle mit _test.go enden:

package main

import "testing"

func TestConv(t *testing.T) {
	num, err := conv("123456789")
	if err != nil {
		t.Fatal(err)
	}
	if num != 123456789 {
		t.Fatal("Number don't match")
	}
}

func TestFailConv(t *testing.T) {
	_, err := conv("")
	if err == nil {
		t.Fatal(err)
	}
}

Innerhalb der Testfunktionen rufst du die conv Funktion auf, die du testen möchtest, und übergibst ihr die gewünschten Testdaten. Wenn die Funktion einen Fehler zurückgibt oder der zurückgegebene Wert nicht mit deinen Erwartungen übereinstimmt, rufst du die Funktion Fatal auf, die eine Meldung protokolliert und dann die Ausführung des Tests beendet.

Probiere es aus: Führe es auf der Kommandozeile aus. Mit dem Flag -v kannst du die Ausführlichkeit erhöhen, damit du siehst, wie viele Testfälle ausgeführt und bestanden werden:

$ go test -v

Das ist es, was du siehst:

=== RUN   TestConv
--- PASS: TestConv (0.00s)
=== RUN   TestFailConv
--- PASS: TestFailConv (0.00s)
PASS
ok  	github.com/sausheong/gocookbook/ch01_general

Wie du siehst, bestehen alle deine Fälle. Nimm nun eine kleine Änderung an deiner conv Funktion vor:

func conv(str string) (num int64, err error) {
	num, err = strconv.ParseInt(str, 2, 64)
	return
}

Anstatt die Zahl zur Basis 10 zu analysieren, verwendest du die Basis 2. Führe den Test noch einmal durch:

=== RUN   TestConv
    general_test.go:8: strconv.ParseInt: parsing "123456789": invalid syntax
--- FAIL: TestConv (0.00s)
=== RUN   TestFailConv
--- PASS: TestFailConv (0.00s)
FAIL
exit status 1
FAIL	github.com/sausheong/gocookbook/ch01_general

Du siehst, dass der TestConv Testfall fehlgeschlagen ist, weil er nicht mehr die erwartete Zahl liefert. Der zweite Testfall ist jedoch erfolgreich, weil er auf einen Fehler testet und diesen gefunden hat.

Die Prüfung wird in Kapitel 18 ausführlicher behandelt.

Get Go Kochbuch now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.