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
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
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
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.
1.3 Ein Hallo-Welt-Programm schreiben
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
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
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
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
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.