Golang Spickzettel
Lernen Sie Golang mit Hands-On Labs
Lernen Sie Go-Programmierung durch praktische Labs und reale Szenarien. LabEx bietet umfassende Go-Kurse, die wesentliche Syntax, Nebenläufigkeitsmuster, Fehlerbehandlung und fortgeschrittene Techniken abdecken. Meistern Sie Go's einzigartige Funktionen wie Goroutinen, Channels und Interfaces, um effiziente, nebenläufige Anwendungen zu erstellen.
Installation & Einrichtung
Go installieren: Herunterladen & Entpacken
Laden Sie Go von der offiziellen Website herunter und installieren Sie es.
# Download von https://golang.org/dl/
# Linux/macOS - nach /usr/local entpacken
sudo tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz
# Zu PATH in ~/.bashrc oder ~/.zshrc hinzufügen
export PATH=$PATH:/usr/local/go/bin
# Installation überprüfen
go version
Paketmanager: Homebrew verwenden (macOS)
Installieren Sie Go mit Homebrew unter macOS.
# Go mit Homebrew installieren
brew install go
# Installation überprüfen
go version
go env GOPATH
Windows-Installation
Installieren Sie Go auf Windows-Systemen.
# .msi-Installer von https://golang.org/dl/ herunterladen
# Installer ausführen und Anweisungen folgen
# In der Eingabeaufforderung überprüfen
go version
echo %GOPATH%
Workspace-Einrichtung: go mod init
Initialisieren Sie ein neues Go-Modul und einen Workspace.
# Neuen Ordner erstellen und Modul initialisieren
mkdir my-go-project
cd my-go-project
go mod init my-go-project
# main.go erstellen
echo 'package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}' > main.go
# Programm ausführen
go run main.go
Umgebungsvariablen
Wichtige Go-Umgebungsvariablen.
# Alle Go-Umgebungsvariablen anzeigen
go env
# Schlüsselvariablen
go env GOROOT # Go Installationsverzeichnis
go env GOPATH # Workspace-Verzeichnis
go env GOOS # Betriebssystem
go env GOARCH # Architektur
IDE-Einrichtung: VS Code
Konfigurieren Sie VS Code für die Go-Entwicklung.
# Go-Erweiterung in VS Code installieren
# Strg+Umschalt+P -> Go: Install/Update Tools
# Hauptfunktionen aktiviert:
# - Syntaxhervorhebung
# - IntelliSense
# - Debugging
# - Testintegration
Grundlegende Syntax & Typen
Paket & Imports
Jede Go-Datei beginnt mit einer Paketdeklaration und Imports.
package main
import (
"fmt"
"strings"
"time"
)
// Einzelner Import
import "os"
Variablen & Konstanten
Variablen und Konstanten deklarieren und initialisieren.
// Variablendeklarationen
var name string = "Go"
var age int = 15
var isOpen bool
// Kurze Deklaration
name := "Golang"
count := 42
// Konstanten
const Pi = 3.14159
const Message = "Hello, Go!"
Melden Sie sich an, um dieses Quiz zu beantworten und Ihren Lernfortschritt zu verfolgen
var name string = "Go" und name := "Go"?:= ist eine kurze Deklaration, die den Typ ableitet, var deklariert den Typ explizit:= kann nur für Konstanten verwendet werdenvar kann nur innerhalb von Funktionen verwendet werdenGrundlegende Datentypen
Grundlegende Typen, die in Go verfügbar sind.
// Numerische Typen
var i int = 42
var f float64 = 3.14
var c complex64 = 1 + 2i
// Texttypen
var s string = "Hello"
var r rune = 'A'
// Boolescher Wert
var b bool = true
Kontrollfluss
Bedingte Anweisungen: if / else / switch
Steuern Sie den Programmfluss mit bedingten Anweisungen.
// If-Anweisungen
if age >= 18 {
fmt.Println("Erwachsen")
} else if age >= 13 {
fmt.Println("Teenager")
} else {
fmt.Println("Kind")
}
// Switch-Anweisungen
switch day {
case "Montag":
fmt.Println("Wochenanfang")
case "Freitag":
fmt.Println("TGIF")
default:
fmt.Println("Regulärer Tag")
}
Schleifen: for / range
Iterieren Sie mit verschiedenen Schleifenkonstrukten.
// Traditionelle for-Schleife
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// While-ähnliche Schleife
for condition {
// Schleifenkörper
}
// Endlosschleife
for {
// Abbruch bei Bedarf
}
Range-Iteration
Iterieren Sie über Slices, Arrays, Maps und Strings.
// Über Slice iterieren
numbers := []int{1, 2, 3, 4, 5}
for index, value := range numbers {
fmt.Printf("Index: %d, Wert: %d\n", index, value)
}
// Über Map iterieren
colors := map[string]string{"red": "#FF0000", "green": "#00FF00"}
for key, value := range colors {
fmt.Printf("%s: %s\n", key, value)
}
// Über String iterieren
for i, char := range "Hello" {
fmt.Printf("%d: %c\n", i, char)
}
Melden Sie sich an, um dieses Quiz zu beantworten und Ihren Lernfortschritt zu verfolgen
range zurück, wenn über ein Slice in Go iteriert wird?Kontrollanweisungen: break / continue
Steuern Sie den Schleifenausführungsfluss.
// Aus der Schleife ausbrechen
for i := 0; i < 10; i++ {
if i == 5 {
break
}
fmt.Println(i)
}
// Aktuelle Iteration überspringen
for i := 0; i < 5; i++ {
if i == 2 {
continue
}
fmt.Println(i)
}
Melden Sie sich an, um dieses Quiz zu beantworten und Ihren Lernfortschritt zu verfolgen
break und continue in Go-Schleifen?Funktionen
Funktionsdeklaration: func
Funktionen mit Parametern und Rückgabewerten definieren.
// Einfache Funktion
func greet(name string) {
fmt.Printf("Hallo, %s!\n", name)
}
// Funktion mit Rückgabewert
func add(a, b int) int {
return a + b
}
// Mehrere Rückgabewerte
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("Division durch Null")
}
return a / b, nil
}
Benannte Rückgaben & Variadische Funktionen
Fortgeschrittene Funktionenmerkmale und Muster.
// Benannte Rückgabewerte
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return // nackte Rückgabe
}
// Variadische Funktion
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
// Verwendung
result := sum(1, 2, 3, 4, 5)
Funktionstypen & Closures
Funktionen als Bürger erster Klasse in Go.
// Funktion als Variable
var multiply func(int, int) int
multiply = func(a, b int) int {
return a * b
}
// Anonyme Funktion
square := func(x int) int {
return x * x
}
// Closure
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
// Verwendung
c := counter()
fmt.Println(c()) // 1
fmt.Println(c()) // 2
Defer-Anweisung
Verzögert die Ausführung von Funktionen, bis die umgebende Funktion zurückkehrt.
func processFile(filename string) {
file, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
defer file.Close() // Wird ausgeführt, wenn die Funktion zurückkehrt
// Dateiinhalt verarbeiten
// file.Close() wird automatisch aufgerufen
}
Datenstrukturen
Arrays & Slices
Feste und dynamische Sequenzen von Elementen.
// Arrays (feste Größe)
var arr [5]int = [5]int{1, 2, 3, 4, 5}
shortArr := [3]string{"a", "b", "c"}
// Slices (dynamisch)
var slice []int
slice = append(slice, 1, 2, 3)
// Slice mit Kapazität erstellen
numbers := make([]int, 5, 10) // Länge 5, Kapazität 10
// Slice-Operationen
slice2 := slice[1:3] // [2, 3]
copy(slice2, slice) // Elemente kopieren
Maps
Schlüssel-Wert-Paare für effiziente Nachschlagevorgänge.
// Map-Deklaration und Initialisierung
var m map[string]int
m = make(map[string]int)
// Kurze Deklaration
ages := map[string]int{
"Alice": 30,
"Bob": 25,
"Carol": 35,
}
// Map-Operationen
ages["David"] = 40 // Hinzufügen/Aktualisieren
delete(ages, "Bob") // Löschen
age, exists := ages["Alice"] // Existenz prüfen
Structs
Gruppieren Sie zusammengehörige Daten mit benutzerdefinierten Typen.
// Struct-Definition
type Person struct {
Name string
Age int
Email string
}
// Struct-Instanzen erstellen
p1 := Person{
Name: "Alice",
Age: 30,
Email: "alice@example.com",
}
p2 := Person{"Bob", 25, "bob@example.com"}
// Felder zugreifen
fmt.Println(p1.Name)
p1.Age = 31
Pointer
Referenzieren Sie Speicheradressen von Variablen.
// Pointer-Deklaration
var p *int
num := 42
p = &num // Adresse von num
// Dereferenzierung
fmt.Println(*p) // Wert an der Adresse (42)
*p = 100 // Wert über Pointer ändern
// Pointer mit Structs
person := &Person{Name: "Alice", Age: 30}
person.Age = 31 // Automatische Dereferenzierung
Methoden & Interfaces
Methoden
Funktionalität an benutzerdefinierte Typen binden.
type Rectangle struct {
Width, Height float64
}
// Methode mit Empfänger
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
// Pointer-Empfänger (kann modifizieren)
func (r *Rectangle) Scale(factor float64) {
r.Width *= factor
r.Height *= factor
}
// Verwendung
rect := Rectangle{Width: 10, Height: 5}
fmt.Println(rect.Area()) // 50
rect.Scale(2) // Modifiziert rect
Interfaces
Definieren Sie Verträge, die Typen erfüllen müssen.
// Interface-Definition
type Shape interface {
Area() float64
Perimeter() float64
}
// Implementierung des Interfaces für Rectangle
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
// Rectangle implementiert nun das Shape-Interface
func printShapeInfo(s Shape) {
fmt.Printf("Fläche: %.2f, Umfang: %.2f\n",
s.Area(), s.Perimeter())
}
Leeres Interface & Typ-Assertionen
Arbeiten mit Werten unbekannter Typen.
// Leeres Interface kann jeden Wert aufnehmen
var i interface{}
i = 42
i = "hallo"
i = []int{1, 2, 3}
// Typ-Assertion
str, ok := i.(string)
if ok {
fmt.Printf("String-Wert: %s\n", str)
}
// Typ-Switch
switch v := i.(type) {
case int:
fmt.Printf("Integer: %d\n", v)
case string:
fmt.Printf("String: %s\n", v)
default:
fmt.Printf("Unbekannter Typ: %T\n", v)
}
Einbettung (Embedding)
Typen durch Einbetten anderer Typen zusammensetzen.
type Person struct {
Name string
Age int
}
type Employee struct {
Person // Eingebetteter Struct
Company string
Salary float64
}
// Verwendung
emp := Employee{
Person: Person{Name: "Alice", Age: 30},
Company: "TechCorp",
Salary: 75000,
}
// Direkter Zugriff auf eingebettete Felder
fmt.Println(emp.Name) // "Alice"
Fehlerbehandlung
Grundlegende Fehlerbehandlung
Verwenden Sie die eingebaute Fehler-Schnittstelle zur Fehlerbehandlung.
import "errors"
// Funktion, die einen Fehler zurückgibt
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("Division durch Null")
}
return a / b, nil
}
// Fehlerprüfung
result, err := divide(10, 2)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Ergebnis: %.2f\n", result)
Benutzerdefinierte Fehler
Erstellen Sie benutzerdefinierte Fehlertypen für spezifische Fehlerbedingungen.
// Benutzerdefinierter Fehlertyp
type ValidationError struct {
Field string
Message string
}
func (e ValidationError) Error() string {
return fmt.Sprintf("Validierungsfehler in %s: %s",
e.Field, e.Message)
}
// Funktion, die benutzerdefinierten Fehler verwendet
func validateAge(age int) error {
if age < 0 {
return ValidationError{
Field: "age",
Message: "muss nicht-negativ sein",
}
}
return nil
}
Fehler-Wrapping
Fügen Sie Kontext zu Fehlern hinzu, während der ursprüngliche Fehler erhalten bleibt.
import "fmt"
// Einen Fehler mit zusätzlichem Kontext umhüllen
func processFile(filename string) error {
file, err := os.Open(filename)
if err != nil {
return fmt.Errorf("Fehler beim Öffnen der Datei %s: %w",
filename, err)
}
defer file.Close()
// Datei verarbeiten...
return nil
}
// Fehler entpacken
err := processFile("missing.txt")
if err != nil {
var pathErr *os.PathError
if errors.As(err, &pathErr) {
fmt.Println("Pfadfehler:", pathErr)
}
}
Panic & Recovery
Behandeln Sie außergewöhnliche Situationen mit panic und recover.
// Funktion, die möglicherweise einen Panic auslöst
func riskyOperation() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Von Panic wiederhergestellt:", r)
}
}()
// Dies löst einen Panic aus
panic("etwas ist schiefgelaufen!")
}
// Verwendung
riskyOperation() // Programm läuft nach Panic weiter
Nebenläufigkeit (Concurrency)
Goroutinen
Leichtgewichtige Threads, die vom Go-Laufzeitsystem verwaltet werden.
import "time"
// Einfache Goroutine
func sayHello() {
fmt.Println("Hallo von Goroutine!")
}
func main() {
// Goroutine starten
go sayHello()
// Anonyme Goroutine
go func() {
fmt.Println("Anonyme Goroutine")
}()
// Warten, bis Goroutinen fertig sind
time.Sleep(time.Second)
}
Channels
Kommunikation zwischen Goroutinen mithilfe von Channels.
// Channel erstellen
ch := make(chan int)
// Gebufferter Channel
buffered := make(chan string, 3)
// Senden und Empfangen
go func() {
ch <- 42 // Wert senden
}()
value := <-ch // Wert empfangen
// Channel schließen
close(ch)
Channel-Muster
Gängige Muster für die Channel-Kommunikation.
// Worker-Muster
func worker(id int, jobs <-chan int, results chan<- int) {
for job := range jobs {
fmt.Printf("Worker %d verarbeitet Job %d\n", id, job)
results <- job * 2
}
}
// Fan-out-Muster
jobs := make(chan int, 100)
results := make(chan int, 100)
// Worker starten
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Jobs senden
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
Select-Anweisung
Behandeln Sie mehrere Channel-Operationen gleichzeitig.
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(time.Second)
ch1 <- "von ch1"
}()
go func() {
time.Sleep(2 * time.Second)
ch2 <- "von ch2"
}()
// Wählt den zuerst verfügbaren Channel
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
case <-time.After(3 * time.Second):
fmt.Println("Timeout")
}
}
Datei-I/O & JSON
Dateioperationen
Dateien mit verschiedenen Methoden lesen und schreiben.
import (
"io/ioutil"
"os"
)
// Gesamte Datei lesen
data, err := ioutil.ReadFile("file.txt")
if err != nil {
log.Fatal(err)
}
content := string(data)
// In Datei schreiben
text := "Hello, World!"
err = ioutil.WriteFile("output.txt", []byte(text), 0644)
// Datei mit mehr Kontrolle öffnen
file, err := os.Open("data.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
CSV-Verarbeitung
CSV-Dateien lesen und schreiben.
import (
"encoding/csv"
"os"
)
// CSV lesen
file, _ := os.Open("data.csv")
defer file.Close()
reader := csv.NewReader(file)
records, _ := reader.ReadAll()
// CSV schreiben
file, _ = os.Create("output.csv")
defer file.Close()
writer := csv.NewWriter(file)
defer writer.Flush()
writer.Write([]string{"Name", "Alter", "Stadt"})
writer.Write([]string{"Alice", "30", "NYC"})
JSON-Verarbeitung
JSON-Daten kodieren und dekodieren.
import "encoding/json"
// Struct für JSON-Mapping
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email,omitempty"`
}
// Marshal (Go zu JSON)
person := Person{Name: "Alice", Age: 30}
jsonData, err := json.Marshal(person)
if err != nil {
log.Fatal(err)
}
// Unmarshal (JSON zu Go)
var p Person
err = json.Unmarshal(jsonData, &p)
HTTP-Anfragen
HTTP-Anfragen stellen und Antworten verarbeiten.
import "net/http"
// GET-Anfrage
resp, err := http.Get("https://api.github.com/users/octocat")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
// POST-Anfrage mit JSON
jsonData := []byte(`{"name":"Alice","age":30}`)
resp, err = http.Post("https://api.example.com/users",
"application/json",
bytes.NewBuffer(jsonData))
Testen
Unit-Tests: go test
Tests mit Go’s Test-Framework schreiben und ausführen.
// math.go
package main
func Add(a, b int) int {
return a + b
}
// math_test.go
package main
import "testing"
func TestAdd(t *testing.T) {
result := Add(2, 3)
expected := 5
if result != expected {
t.Errorf("Add(2, 3) = %d; erwartet %d", result, expected)
}
}
// Tests ausführen
// go test
// go test -v (ausführlich)
Tabellengetriebene Tests
Mehrere Fälle effizient testen.
func TestAddMultiple(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive Zahlen", 2, 3, 5},
{"mit Null", 0, 5, 5},
{"negative Zahlen", -1, -2, -3},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("erhielt %d, erwartet %d", result, tt.expected)
}
})
}
}
Benchmarking
Leistungsmessung von Funktionen.
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(2, 3)
}
}
// Benchmarks ausführen
// go test -bench=.
// go test -bench=BenchmarkAdd -benchmem
Beispieltests
Erstellen Sie ausführbare Beispiele, die als Dokumentation dienen.
import "fmt"
func ExampleAdd() {
result := Add(2, 3)
fmt.Printf("2 + 3 = %d", result)
// Output: 2 + 3 = 5
}
func ExampleAdd_negative() {
result := Add(-1, -2)
fmt.Printf("(-1) + (-2) = %d", result)
// Output: (-1) + (-2) = -3
}
// Beispiele ausführen
// go test -run Example
Go Modules & Pakete
Modulverwaltung
Go-Module initialisieren und die Abhängigkeitsverwaltung verwalten.
# Neues Modul initialisieren
go mod init github.com/username/project
# Abhängigkeiten hinzufügen
go get github.com/gorilla/mux
go get -u github.com/gin-gonic/gin # Auf neueste aktualisieren
# Unbenutzte Abhängigkeiten entfernen
go mod tidy
# Abhängigkeiten herunterladen
go mod download
# Abhängigkeiten lokal "vendorn"
go mod vendor
go.mod Datei
Verständnis der Moduldefinitionsdatei.
module github.com/username/myproject
go 1.21
require (
github.com/gorilla/mux v1.8.0
github.com/stretchr/testify v1.8.4
)
require (
github.com/davecgh/go-spew v1.1.1 // indirekt
github.com/pmezard/go-difflib v1.0.0 // indirekt
)
Pakete erstellen
Code in wiederverwendbare Pakete strukturieren.
// Paketstruktur
// myproject/
// ├── go.mod
// ├── main.go
// └── utils/
// ├── math.go
// └── string.go
// utils/math.go
package utils
// Exportierte Funktion (beginnt mit Großbuchstaben)
func Add(a, b int) int {
return a + b
}
// Private Funktion (beginnt mit Kleinbuchstaben)
func multiply(a, b int) int {
return a * b
}
// main.go
package main
import (
"fmt"
"github.com/username/myproject/utils"
)
func main() {
result := utils.Add(5, 3)
fmt.Println(result)
}
Häufige Go-Befehle
Wesentliche Befehle für die Go-Entwicklung.
# Go-Programm ausführen
go run main.go
# Ausführbare Datei erstellen
go build
go build -o myapp # Benutzerdefinierter Name
# Binärdatei in GOPATH/bin installieren
go install
# Code formatieren
go fmt ./...
# Code auf Probleme überprüfen
go vet ./...
# Build-Cache bereinigen
go clean -cache