Skip to main content
Entwickler Themen
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

7.2.5. Nebenläufigkeit und Context

Go macht Nebenläufigkeit leicht – und Leaks leicht. Jede Goroutine braucht eine klare Exit-Bedingung; Libraries starten sie selten „heimlich“ hinter einer normalen Funktion.

Share memory by communicating – Mutexes bleiben ok

Ownership und Daten über Channels zu reichen, sodass nur eine Goroutine den Wert anfasst, ist der klassische Rat. Mutexes sind richtig, wenn sie klarer sind (z. B. ein einfacher Zähler). Proverbs: Channels orchestrate; mutexes serialize. Effective Go warnt davor, den Channel-Rat zu übertreiben.

jobs := make(chan Job)
go worker(jobs)

var (
	mu sync.Mutex
	n  int
)
mu.Lock()
n++
mu.Unlock()

Context: erster Parameter, kein Struct-Feld

context.Context trägt Deadlines, Cancellation und request-scoped Werte über API-Grenzen.

func DoSomething(ctx context.Context, arg Arg) error {
	// ... ctx nutzen ...
}
  • ctx explizit die Aufrufkette hinunterreichen (meist erster Parameter).
  • Nicht in Structs speichern (als Methodenargument übergeben); seltene Ausnahme bei fremden Interfaces.
  • Nie nil Context; unsicher → context.TODO, Top-Level mit Grund → context.Background.
  • Abgeleitete Contexts mit WithCancel / WithTimeout / WithDeadline; nach Gebrauch canceln.
  • WithValue nur für request-scoped Daten über Prozess-/API-Grenzen – nicht für optionale Parameter.

Goroutine-Lebensdauer

Blockierte Goroutinen werden nicht vom GC eingesammelt. Exit-Bedingungen dokumentieren, wenn sie nicht offensichtlich sind. Bevorzugt synchrone APIs – der Caller steuert die Parallelität.

ctx, cancel := context.WithCancel(parent)
defer cancel()

done := make(chan struct{})
go func() {
	defer close(done)
	for {
		select {
		case <-ctx.Done():
			return
		case job := <-jobs:
			handle(job)
		}
	}
}()

// später: cancel(); <-done

sync.WaitGroup.Go ist dem manuellen Add + go + defer Done vorzuziehen. Die gestartete Funktion darf nicht panicen.

Channel-Puffer

Effective Go zeigt gepufferte Channels (z. B. Parallelisierung mit make(chan int, numCPU)). Uber bevorzugt ungepuffert oder Größe 1 und will jede andere Größe begründet sehen – das ist Org-Stil, keine Sprachnorm. In jedem Fall: Ownership und Backpressure klar halten.

Diese Seite gehört zu 7.2. Clean Code.