Skip to content

Modul 2: Syntax-Grundlagen — Variablen, Kontrollfluss, Funktionen

Go-Syntax: Typen und Variablen (var, :=, const), Kontrollfluss (if, switch, for), Funktionen mit mehreren Rückgaben, Slices & Maps sowie Structs und Methoden.

Fortschritt0/5 Lektionen
6

Variablen & Typen: var, := und const

Lektion 6 von 5

Drei Wege, eine Variable zu deklarieren

In Go gibt es zwei Hauptwege plus const. Die Kurzschreibweise := ist der Go-Idiom — sie übernimmt den Typ automatisch vom rechten Wert.

package main

import "fmt"

func main() {
	var name string = "ana"  // explizit: Typ + Wert
	var city string          // explizit, Wert leer ""
	age := 30                 // Kurzform: Typ wird abgeleitet (int)

	const pi = 3.14159        // Konstanten: nie geändert, nie gelöscht

	fmt.Println(name, city, age, pi)
}

Die Grundtypen

Go ist statisch typisiert: Jede Variable hat einen festen Typ.

TypBeispieleHinweis
int, int32, int6442Architektur-abhängig vs. feste Breite
float64, float323.14float64 ist der Default
booltrue, false
string"hallo"immutable, UTF-8
byte, rune'a', 'ä'rune = Unicode-Zeichen (int32)

Warum : = statt var (meist)?

Die Kurzform := ist kürzer, und der Typ steht direkt am Wert sichtbar. var brauchst du, wenn du ohne Initialwert deklarierst (z. B. in var list []string). Wichtig: := funktioniert nur innerhalb von Funktionen. Auf Paketebene heißt es var.

var counter int      // Paket-Level: nur var erlaubt

func main() {
	x := 10            // neu deklarieren
	x = x + 1          // zuweisen, kein := (x gibt es schon)
	// x := 20          // FEHLER: no new variables on left side of :=
	_ = x
}

Die leere Variable _ verwirft Werte bewusst — Go zwingt dich, alles zu nutzen, was du deklarierst.

✅ Wichtige Erkenntnisse

Haken setzen, um deinen Lernfortschritt zu markieren:

    7

    Kontrollfluss: if, switch und die einzige Schleife for

    Lektion 7 von 5

    if mit Bedingung + Statement

    if kann eine Initialisierung voranstellen — das Muster, das du überall in Go-Quellcode findest:

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	if len(os.Args) < 2 {
    		fmt.Println("Bitte ein Argument angeben")
    		return
    	}
    	name := os.Args[1]
    
    	// Go-Idiom: Statement ; Bedingung
    	if msg := "Hallo " + name; len(name) < 3 {
    		fmt.Println(msg, "(kurzer Name)")
    	} else {
    		fmt.Println(msg)
    	}
    }
    

    for — die einzige Schleife

    Kein while, kein do-while. Alle Schleifen sind for — mit drei Varianten:

    // 1) Klassisch (wie C)
    for i := 0; i < 5; i++ {
    	fmt.Println(i)
    }
    
    // 2) Als while
    n := 3
    for n > 0 {
    	n--
    }
    
    // 3) Range über Slices, Maps, Strings (Modul 2, Lektion 9)
    for i, v := range []string{"a", "b", "c"} {
    	fmt.Println(i, v)
    }
    

    switch — automatisches break

    Go-switch hat kein Durchfallen: Am Ende jedes Case ist automatisch break. Ein Komma listet mehrere Fälle, default ist optional.

    status := "offen"
    switch status {
    case "offen", "in arbeit":
    	fmt.Println("Aktiv")
    case "geschlossen":
    	fmt.Println("Fertig")
    default:
    	fmt.Println("Unbekannt")
    }
    

    ✅ Wichtige Erkenntnisse

    Haken setzen, um deinen Lernfortschritt zu markieren:

      8

      Funktionen: mehrere Rückgaben, benannte Rückgaben, defer

      Lektion 8 von 5

      Der Go-Idiom: (wert, fehler)

      Go-Funktionen können mehrere Werte zurückgeben. Zusammen mit error als zweitem Rückgabewert entsteht das berühmte Go-Fehlermuster — explizit statt Exceptions.

      package main
      
      import (
      	"fmt"
      	"strconv"
      )
      
      // Mehrere Rückgaben: (Ergebnis, Fehler)
      func parseAge(s string) (int, error) {
      	n, err := strconv.Atoi(s)
      	if err != nil {
      		return 0, fmt.Errorf("keine Zahl: %q", s)
      	}
      	return n, nil
      }
      
      func main() {
      	age, err := parseAge("32")
      	if err != nil {
      		fmt.Println("Fehler:", err)
      		return
      	}
      	fmt.Println("Alter:", age)
      }
      

      Benannte Rückgabewerte

      Du kannst Rückgabewerte benennen und einfach return schreiben; die Variablen werden mit ihrem Nullwert angelegt.

      func divide(a, b float64) (result float64, err error) {
      	if b == 0 {
      		err = fmt.Errorf("Division durch null")
      		return
      	}
      	result = a / b
      	return
      }
      

      defer — Aufräumen direkt am Ort

      defer schiebt einen Aufruf ans Ende der Funktion. Damit steht das Schließen direkt neben dem Öffnen — das wichtigste Go-Muster für Dateien, Verbindungen, Locks.

      import "os"
      
      func readFile(path string) (string, error) {
      	f, err := os.Open(path)
      	if err != nil {
      		return "", err
      	}
      	defer f.Close() // läuft am Ende der Funktion — auch bei frühzeitigem return
      
      	buf := make([]byte, 1024)
      	n, _ := f.Read(buf)
      	return string(buf[:n]), nil
      }
      

      ✅ Wichtige Erkenntnisse

      Haken setzen, um deinen Lernfortschritt zu markieren:

        9

        Slices & Maps: make, append, range

        Lektion 9 von 5

        Slices — das dynamische Array

        []T ist ein Slice: ein Fenster auf ein Array, das mit append wächst. Literale, make, und das Range-Iterieren decken 99 % der Arbeit ab.

        package main
        
        import "fmt"
        
        func main() {
        	// Literal
        	nums := []int{1, 2, 3}
        
        	// make: Slice mit Platz für 0 Elemente, Kapazität 10
        	items := make([]string, 0, 10)
        	items = append(items, "erste")
        
        	// append wächst automatisch
        	for i := 4; i <= 6; i++ {
        		nums = append(nums, i)
        	}
        
        	// Slicing: [vom, bis) — halb offen
        	tail := nums[1:3] // [2 3]
        
        	// range: Index + Wert
        	for i, v := range nums {
        		fmt.Println(i, v, cap(items))
        	}
        	_ = tail
        }
        

        Maps — der schnelle Nachschlag

        map[K]V ist der assoziative Speicher. Der Doppel-Wert-Idiom v, ok prüft, ob ein Schlüssel existiert — die Go-Antwort auf „key not found".

        scores := map[string]int{"ana": 95}
        scores["ben"] = 88
        
        delete(scores, "ben")
        
        val, ok := scores["ana"]
        if !ok {
        	fmt.Println("fehlt")
        }
        fmt.Println("ana:", val)
        

        Der große Unterschied zu anderen Sprachen

        • Slices werden per Referenz übergeben (eine Änderung wirkt überall); Werte und Structs (Lektion 10) werden per Wert kopiert.
        • append kann die Kapazität wechseln — hältst du eine alte Referenz, zeigt die auf den alten Speicher.
        func main() {
        	a := []int{1, 2, 3}
        	b := a
        	b[0] = 99 // ändert auch a[0] — Slice teilt das Array
        	fmt.Println(a[0]) // 99
        }
        

        ✅ Wichtige Erkenntnisse

        Haken setzen, um deinen Lernfortschritt zu markieren:

          10

          Structs & Methoden: eigene Typen

          Lektion 10 von 5

          struct — dein eigener Typ

          Ein struct bündelt Felder. Der Typ empfängt Methoden über einen Receiver — das ist Go-Weise, Klassen zu ersetzen: Daten und Methoden, ohne Vererbung.

          package main
          
          import "fmt"
          
          type User struct {
          	Name string
          	Age  int
          }
          
          // Wert-Receiver: arbeitet auf einer Kopie
          func (u User) Greeting() string {
          	return "Hallo, " + u.Name
          }
          
          // Pointer-Receiver: ändert das Original
          func (u *User) Birthday() {
          	u.Age++
          }
          
          func main() {
          	u := User{Name: "ana", Age: 30}
          	fmt.Println(u.Greeting())
          
          	u.Birthday()
          	fmt.Println(u.Age) // 31
          }
          

          Wert- vs. Pointer-Receiver

          ReceiverKopie?Wann
          func (u User)ja (Kopie)Read-only oder kleine Werte
          func (u *User)nein (Original)Zustand ändern oder große Strukturen

          Faustregel: Konsistenz — wenn eine Methode einen Pointer nimmt, dann alle Methoden des Typs, sonst verwirrt das.

          Stringer: der Go-ToString

          Mit String() string auf einem Wert-Receiver überschreibst du die Standard-Ausgabe bei fmt.Println — das Go-Pendant zu toString(), ohne Klassenhierarchie:

          func (u User) String() string {
          	return fmt.Sprintf("%s (%d Jahre)", u.Name, u.Age)
          }
          
          // fmt.Println(u) → ana (30 Jahre)
          

          Wochen-Check Modul 2

          ✅ Wichtige Erkenntnisse

          Haken setzen, um deinen Lernfortschritt zu markieren:

            This site uses essential cookies for Stripe payments. No tracking cookies.