Go Grundlagen

6 Kernkonzepte
Die wichtigsten Go-Konzepte für den Einstieg: Variablen & Datentypen · Kontrollstrukturen · Funktionen · Packages · Fehlerbehandlung · Zeiger Go (Golang) ist eine statisch typisierte, kompilierte Programmiersprache von Google – bekannt für ihre Einfachheit, Performance und hervorragende Concurrency-Unterstützung. Diese Cheatsheet fasst die grundlegenden Konzepte zusammen.

Variablen & Datentypen – Deklaration und Typen

var · := · string · int · bool
var name string = "Anna" age := 30 // Kurzdeklaration var isActive bool = true const pi = 3.14159 // Konstante

Go ist statisch typisiert. Variablen können mit var oder der Kurzdeklaration := (nur innerhalb von Funktionen) deklariert werden. Der Typ wird entweder explizit angegeben oder vom Compiler inferiert.

Wichtige Datentypen

Typ Beschreibung Beispiel
string Zeichenkette "Hallo"
int, int8, int16, int32, int64 Ganzzahlen 42, -5
uint, uint8, uint16, uint32, uint64 Vorzeichenlose Ganzzahlen 42
float32, float64 Fließkommazahlen 3.14
bool Wahrheitswerte true, false
byte Alias für uint8 65 ('A')
rune Alias für int32 (Unicode) 'Ä'
any Interface{} (beliebiger Typ) 42, "text"
Beispiele
package main
import "fmt"
func main() {
// Explizite Deklaration
var name string = "Anna"
var age int = 30
// Kurzdeklaration (Typinferenz)
city := "Berlin" // string
population := 3645000 // int
// Mehrere Variablen
var x, y int = 1, 2
a, b := "foo", 42
// Konstante
const pi = 3.14159
// Nullwerte (Zero Values)
var emptyString string // ""
var emptyInt int // 0
var emptyBool bool // false
}
Tipp: Die Kurzdeklaration := ist die idiomatische Weise, Variablen in Go zu deklarieren. Sie kann nur innerhalb von Funktionen verwendet werden. Globale Variablen verwenden var.

Kontrollstrukturen – if, for, switch

if · for · switch · range
if x > 0 { fmt.Println("Positiv") } for i := 0; i < 5; i++ { /* ... */ } switch day { case "Mon": /* ... */ }

Go hat eine übersichtliche Auswahl an Kontrollstrukturen. Es gibt kein while – stattdessen wird for für alle Schleifen verwendet. switch ist flexibel und benötigt kein break.

Beispiele
package main
import "fmt"
func main() {
// if mit Statement
if x := 10; x > 0 {
fmt.Println("Positiv")
} else if x == 0 {
fmt.Println("Null")
} else {
fmt.Println("Negativ")
}
// for (while-ähnlich)
sum := 0
for sum < 10 {
sum += sum
}
// for-range (über Slice/Map)
fruits := []string{"Apfel", "Banane", "Kirsche"}
for idx, fruit := range fruits {
fmt.Printf("%d: %s\n", idx, fruit)
}
// switch
day := "Montag"
switch day {
case "Montag", "Dienstag":
fmt.Println("Anfang der Woche")
case "Samstag", "Sonntag":
fmt.Println("Wochenende")
default:
fmt.Println("Mitte der Woche")
}
}
Tipp: In switch wird kein break benötigt – Go springt automatisch zum nächsten case nicht durch. Verwenden Sie fallthrough, um das Verhalten zu ändern.

Funktionen – Definition und Rückgabewerte

func · return · Mehrere Rückgabewerte
func add(a int, b int) int { return a + b } func divide(a, b int) (int, error) { /* ... */ }

Funktionen werden mit func deklariert. Go unterstützt mehrere Rückgabewerte – besonders nützlich für die Rückgabe von Ergebnissen und Fehlern. Die Parameterliste kann verkürzt werden, wenn benachbarte Parameter den gleichen Typ haben.

Beispiele
package main
import "fmt"
// Einfache Funktion
func greet(name string) string {
return "Hallo " + name
}
// Mehrere Rückgabewerte
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("Division durch Null")
}
return a / b, nil
}
// Named Return Values
func stats(nums []int) (sum int, count int) {
count = len(nums)
for _, n := range nums {
sum += n
}
return // naked return
}
// Variadic Function (beliebig viele Argumente)
func sum(nums ...int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}
// Funktion als Wert
fn := func(x int) int { return x * 2 }
fmt.Println(fn(5))
Tipp: Mehrere Rückgabewerte sind idiomatisch für Fehlerbehandlung – das erste Ergebnis ist der Wert, das zweite ein error, der bei Erfolg nil ist.

Packages – Code organisieren und importieren

package · import · main
// main.go package main import "fmt" import "math/rand" func main() { fmt.Println("Hallo") }

Packages sind die Einheit der Code-Organisation in Go. Jede Go-Datei beginnt mit einer package-Deklaration. main ist das ausführbare Package. Importe werden mit import eingebunden.

Beispiele
// utils/math.go
package utils
// Großbuchstabe = exported (öffentlich)
func Add(a, b int) int {
return a + b
}
// Kleinbuchstabe = private (nur innerhalb des Packages)
func subtract(a, b int) int {
return a - b
}
// main.go
package main
import (
"fmt"
"math/rand"
// Eigene Packages (relativer Pfad)
"./utils"
// Alias für Package
r "math/rand"
)
func main() {
result := utils.Add(3, 5)
fmt.Println(result)
fmt.Println(r.Intn(100))
}
// Import mit Unterstrich (nur init)
import _ "image/png"
Tipp: Exportierte (öffentliche) Funktionen und Variablen beginnen mit einem Großbuchstaben. Private Bezeichner beginnen mit Kleinbuchstaben. Das ist das einzige Sichtbarkeitskonzept in Go.

Fehlerbehandlung – error-Interface

error · fmt.Errorf · errors.Is
import "errors" var ErrNotFound = errors.New("nicht gefunden") func find(id int) (string, error) { if id < 0 { return "", ErrNotFound } return "Daten", nil }

Fehlerbehandlung in Go erfolgt über das error-Interface. Funktionen geben oft ein Ergebnis und einen Fehler zurück – der Fehler wird geprüft, und bei nil ist alles in Ordnung.

Beispiele
package main
import (
"errors"
"fmt"
)
var ErrInvalidAge = errors.New("Ungültiges Alter")
func validateAge(age int) error {
if age < 0 || age > 150 {
return fmt.Errorf("Alter %d ungültig", age)
}
return nil
}
func main() {
// Standard-Fehlerbehandlung
result, err := someFunction()
if err != nil {
fmt.Println("Fehler:", err)
return
}
fmt.Println(result)
// Fehler mit Context
ageErr := validateAge(-5)
if ageErr != nil {
fmt.Printf("Validierungsfehler: %v\n", ageErr)
}
// Fehler vergleichen (errors.Is)
if errors.Is(ageErr, ErrInvalidAge) {
fmt.Println("Spezifischer Fehler!")
}
// panic und recover (für fatale Fehler)
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered:", r)
}
}()
panic("etwas ist schief gelaufen")
}
Tipp: Die idiomatische Fehlerbehandlung in Go ist explizit und ohne Exceptions. Jede Funktion, die fehlschlagen kann, sollte einen error zurückgeben, der direkt geprüft wird.

Zeiger – & und *

*T · & · new · nil
var x int = 42 var p *int = &x // Zeiger auf x fmt.Println(*p) // 42 (Dereferenzierung) *p = 10 // x wird zu 10

Zeiger speichern die Speicheradresse eines Werts. Sie ermöglichen es, Werte in Funktionen zu modifizieren, ohne Kopien zu erstellen. Der Typ *T ist ein Zeiger auf einen Wert vom Typ T.

Beispiele
package main
import "fmt"
// Funktion mit Zeiger-Parameter
func increment(p *int) {
*p++
}
// Funktion mit Wert (Kopie)
func incrementCopy(v int) int {
return v + 1
}
func main() {
x := 5
increment(&x)
fmt.Println(x) // 6
// new() – Zeiger auf Zero-Value
p := new(int)
fmt.Println(*p) // 0
// nil-Zeiger
var nilPtr *int
if nilPtr == nil {
fmt.Println("Ist nil")
}
// Zeiger auf Struct
type Person struct { Name string; Age int }
person := &Person{Name: "Anna", Age: 30}
fmt.Println(person.Name) // Anna (automatische Dereferenzierung)
}
Tipp: In Go werden Argumente als Kopien übergeben. Verwenden Sie Zeiger, um Werte in Funktionen zu modifizieren. Für große Structs sind Zeiger oft effizienter, da keine Kopie erstellt wird.

Go im Überblick

:= Kurzdeklaration
Typinferenz
defer Aufschieben
Am Ende ausführen
go Goroutine
Concurrency
chan Channel
Kommunikation
interface Interfaces
Duck-Typing
_ Blank Identifier
Werte ignorieren

Quick Summary

:=
Variablen
for
Schleifen
func
Funktionen
package
Packages
error
Fehlerbehandlung
*
Zeiger
age := 30 · func add(a, b int) int { return a + b } · if err != nil { ... }