Teil 2 - Grundlagen
Wir haben nun unsere main Datei, damit können wir uns nun mit Go vertraut machen. Die folgenden Beispiele sind mehr ein Handbuch und noch nicht Teil des Beispielprojekts.
Packages
Go ist eine Sprache die sehr auf Pakete/Packages aufbaut. Jede Anwendung ist mindestens ein package und kann beliebig viele packages einbinden und benutzen.
Um unsere Anwendung zu starten müssen wir daher erst ein package definieren.
package main
Go unterschiedet nicht nach Dateien sondern nach packages, daher kann euer code über viele Dateien verteilt sein so lange er das selbe package nutzt (oder importiert wird).
Naming
In Go ist es sehr bedeutend wie eine Variable, Funktion, Konstante, etc. benannt wird. Zum einen setzt man in Go auf sog. CamelCase, also die Verbindung von Groß- und Kleinschreibung:
var wichtigeVariableNummerEins = 1
Zum Anderen hat der erste Buchstabe eine große Bedeutung für das Scope des Objekts. Wenn der erste Buchstabe des Namens klein ist, so gilt das Objekt nur in seinem eigenen Scope (in einer Funktion oder einem Package). Ist der Buchstabe aber groß, so können auch andere Funktionen auf das Objekt zugreifen.
Wichtig ist also eine ordentliche Bennenung und das Bedenken des ersten Buchstabens
Functions
Wie in den meisten Sprachen, braucht unsere Anwendung nun einen Startpunkt. Das ist typischerweise die main Funktion.
In Go werden Funktionen wie folgt definiert:
func main() {
fmt.Printf("hello, world\n")
}
Ihr seht, dass dies etwas kürzer ist als die meisten anderen Sprachen. Wichtig ist aber auch, dass es keine Semicolons o.Ä. gibt.
Wenn eine Funktion einen Wert zurück geben soll, dann wird das wie folgt definiert:
func add(a, b int) int {
return a + b
}
Ihr seht, dass Parameter für die Funktion wie üblich in der Klammer übergeben werden. Eine Besonderheit ist hierbei, dass Go kleine aber feine Abkürzungen erlaubt. In diesem Fall sollen a und b 'int' Werte sein, daher reicht es wenn der letzte Parameter mit dem Typ versehen wird.
Der Rückgabewert wird nach den Klammern gesetzt.
Zusätzlich ist auch wichtig, dass auch der Rückgabewert flexibel ist. So können auch viele Werte gleichzeitig zurückgegeben werden:
func swap(a, b int) (int, int) {
return b, a
}
Die Funktion gibt die beiden Werte in umgekehrter Reihenfolge zurück. Wichtig hierbei ist, dass die beiden int's diesmal in Klammern stehen, da sie mehrere sind.
Auch die Rückgabewerte können benannt werden:
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
Variables
Wie in anderen Sprachen können Variablen auf verschiedenen Ebenen definiert werden. Dazu zählen auch die packages und functions.
Eine Variable definiert man wie folgt:
var x int
var y int = 42
Sollte eine Variable nicht initialisiert werden, bekommt sie einen 'null-Wert'. Dieser hängt vom Typ der Variable ab (int->0, string->"", bool->false).
Wie in den Parametern einer Funktion können auch gewöhnliche Variablen gleichzeitig definiert werden:
var x, y int = 1, 2
In diesem Beispiel werden erst zwei Variablen x, y definiert und dann mit den Werten x=1 und y=2 initialisiert.
Praktisch bei sofort initilaisierten Variablen ist, dass diese immer den Typ des Werts wählt. Dadurch kann der Typ eingespart werden:
var x, y, z = 42, false, "Hello"
Als Resultat hat x den Typ int, y den Typ bool und z den Typ string.
Innerhalb von Funktionen (und nur dort) können Variablen auch noch kürzer Initialisiert werden:
func num() (int, int, int) {
var i, j int = 1, 2
k := 3
return i + j + k
}
Wie ihr seht, wurde die Variable k nicht wie i und j explizit definiert. Durch den Operator := wird sie gleichzeitig definiert und initialisiert. Auch das ist mit mehreren Variablen (typen unabhängig) gleichzeitig möglich:
func num() (int, int, int) {
i, j, k := 1, 2, 3
return i + j + k
}
Auch Go beherrscht Konstanten. Diese können jedoch nicht durch := definiert werden, sondern erfordern folgende Syntax:
const Pi = 3.14
Types
In Go gibt es ein paar Typen die immer verfügbar sind, weitere können aber importiert werden.
Hier eine Liste der Standard Typen:
- bool
- string
- int
- int8/int16/int32/int64
- uint
- uint8/uint16/uint32/uint64
- uintptr
- byte // alias for uint8
- rune // alias for int32 // represents a Unicode code point
- float32/float64
- complex64/complex128
Types können mit der Funktion T(v) umgewandelt werden. So kann ein int in andere Typen umgewandelt werden:
i := 42
f := float64(i)
u := uint(f)
Imports
Nachdem wir bisher alles mit Go Grundlagen erledigt haben, ist es nun an der Zeit die ersten Packages zu importieren.
Go liefert eine Menge an Paketen und noch mehr können von der Community importiert werden.
In unserem Fall sollte das Importieren eigentlich durch Visual Studio Code erfolgen. Das testen wir indem wir mit unserer main function beginnen. Ein übliches "Hello World" ist als erster Schritt ganz in ordnung:
package main
func main() {
fmt.Prinln("Hello World!")
}
Wie ihr seht, nutzen wir hier fmt.Println() was kein Teil der Go basics ist. Wenn wir nun in vscode speichern, sollte uns dieses das nötige Paket fmt importieren.
Visual Studio Code nutzt meist ganz automatisch den multiline import:
import (
"fmt"
)
Es können aber auch nur einzelne Zeilen für jeden Import verwendet werden:
import "fmt"
Build and Run
Wir haben nun ein kleines Hello World Programm, doch wie bekommen wir dieses nun dazu auch zu starten?
Go bietet ein Tool für die Kommandozeile, das alles kann was wir brauchen. Am einfachsten ist es in vscode das Terminal zu öffnen (Ctrl(CMD)+Shift+P -> "view terminal"):Mit dem integrierten Terminal bietet uns vscode ein großartiges Feature und wir müssen den Editor nicht mehr verlassen um unseren Code zu testen:
go build
Baut alles Go im aktuellen Ordner. Das Ergebnis ist eine Binärdatei die wir ausführen können (unter Windows eine gobasicstut.exe). Mit 'go install' können wir den gebauten Code installieren, wodurch er in go/bin verschoben wird.
Für unsere Zwecke reicht aber auch einfach, die main.go zu starten. Wir können daher einfach diese mit dem go Befehl ausführen:
go run main.go
Das Ergebnis sollte für sich sprechen.