Golang Interview Fragen: Concurrency, Goroutines und Channels erklärt

Golang Interview Fragen prüfen, wie sicher Go Entwickler die Sprachgrundlagen beherrschen und vor allem die Werkzeuge für Nebenläufigkeit: Goroutines, Channels, select, das Paket sync und context. Seit 2012 leite ich Webprojekte, und bei der Auswahl von Backend Entwicklern stelle ich genau diese Fragen selbst.
In diesem Beitrag halte ich die allgemeinen Go Fragen kurz und lege den Schwerpunkt auf Nebenläufigkeit. Zu jeder Frage erfahren Sie, was der Interviewer eigentlich misst, und Sie sehen ein kurzes Codebeispiel. Weitere Beiträge dieser Art finden Sie in der Kategorie Software.
Welche Golang Interview Fragen kommen am häufigsten vor?
Golang Interview Fragen verteilen sich auf vier Ebenen: Sprachgrundlagen, Goroutines und Scheduler, Channels mit select sowie praxisnahe Muster mit sync und context. Bei Positionen auf mittlerem Niveau betrifft meist mehr als die Hälfte der Fragen die Nebenläufigkeit, denn Teams wählen Go oft für stark belastete Dienste.
Deshalb sollten Sie keine Definitionen auswendig lernen. Schreiben Sie stattdessen kleine Programme. Bauen Sie zum Beispiel einen Worker Pool, eine Anfrage mit Timeout und einen Zähler mit Race Condition, und reparieren Sie dann den Zähler. Danach wirken die meisten Fragen vertraut. Außerdem gewöhnen Sie sich daran, Code laut zu erklären.
Was misst der Interviewer mit Go Fragen eigentlich?
Der Interviewer achtet auf drei Dinge. Erstens: Können Sie den Begriff korrekt erklären? Zweitens: Erkennen Sie das Risiko? Drittens: Können Sie beschreiben, wie Sie das Werkzeug in echtem Code eingesetzt haben? Die Definition kennen viele. Allerdings können nur wenige erklären, wie sich ein Goroutine Leak in Produktion bemerkbar macht.
Am meisten schätze ich Kandidaten, die sagen: „Das weiß ich nicht genau, aber so würde ich es testen.“ Wer zum Beispiel den Geschwindigkeitsunterschied zwischen sync.Map und einer Map mit Lock nicht kennt, aber einen Benchmark vorschlägt, sendet ein starkes Signal. Kurz gesagt zählt für mich der Weg genauso viel wie die Antwort.
- Genauigkeit: Goroutines, Channels und Mutex klar unterscheiden.
- Risikobewusstsein: Deadlocks, Data Races und Leaks erkennen.
- Praxis: Race Detector, pprof und Tests schon benutzt haben.
- Kommunikation: Eine Designentscheidung mit Gründen verteidigen.
Was ist eine Goroutine und wie unterscheidet sie sich von einem Thread?
Eine Goroutine ist eine leichtgewichtige Ausführungseinheit, die die Go Laufzeit verwaltet. Sie schreiben das Schlüsselwort go vor einen Funktionsaufruf, und die Funktion läuft nebenläufig im selben Adressraum. Der wichtigste Unterschied zum Thread des Betriebssystems: Nicht der Kernel plant die Ausführung, sondern die Go Laufzeit.
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
gruessen("Anna")
}()
wg.Wait()
}
Laut den Release Notes zu Go 1.4 startet der Stack einer Goroutine mit 2048 Byte und wächst bei Bedarf. Deshalb lassen sich Zehntausende Goroutines starten. Allerdings endet eine gute Antwort hier nicht. Goroutines sind günstig, aber nicht kostenlos. Code ohne Obergrenze kann also trotzdem Speicher oder einen Verbindungspool erschöpfen.
Das Beispiel wartet übrigens bewusst mit einer WaitGroup. Eine häufige Falle ist, stattdessen mit time.Sleep zu warten; die Pause ist dann entweder zu kurz oder verschwendet Zeit. Der Interviewer fragt oft, wie Sie das beheben würden. Richtig ist, das Warten an ein Synchronisationswerkzeug zu binden, also an eine WaitGroup oder einen Channel.
Wie arbeitet der Go Scheduler mit dem Modell aus G, M und P?
Den Go Scheduler erklären Sie mit drei Buchstaben. G steht für eine Goroutine, M für einen Thread des Betriebssystems und P für einen Prozessorkontext. Eine G läuft nur, wenn ein M einen P hält. Somit entspricht die Zahl der Threads, die gleichzeitig Go Code ausführen, der Zahl der P, also GOMAXPROCS.
Jeder P besitzt eine eigene lokale Warteschlange. Hat ein P keine Arbeit mehr, stiehlt er Aufgaben aus anderen Warteschlangen; das nennt man Work Stealing. Zudem gibt der Scheduler den P an einen anderen M weiter, sobald eine Goroutine in einem Systemaufruf blockiert. So laufen die übrigen Goroutines weiter.
Hier sucht der Interviewer Intuition statt Detailwissen. Ein Beispiel: Endet die Nebenläufigkeit, wenn Sie GOMAXPROCS auf 1 setzen? Nein. Die Nebenläufigkeit bleibt, nur die Parallelität fällt weg. Genau diese Unterscheidung führt zur nächsten Frage.
Was ist der Unterschied zwischen Concurrency und Parallelism?
Concurrency bedeutet, ein Programm so zu strukturieren, dass es mehrere Aufgaben in überlappenden Zeiträumen verwalten kann. Parallelism bedeutet, dass diese Aufgaben physisch im selben Moment auf verschiedenen Kernen laufen. Auf einem Rechner mit einem Kern können Sie nebenläufig programmieren. Parallel läuft dort allerdings nichts.
Das Go Team formuliert es oft so: Nebenläufigkeit betrifft das Design, Parallelität die Ausführung. Daher betont eine starke Antwort, dass Go Ihnen Werkzeuge für nebenläufiges Design gibt, während Laufzeit und Hardware für Parallelität sorgen.
| Begriff | Bedeutung | Werkzeug in Go |
|---|---|---|
| Concurrency | Überlappende Aufgaben verwalten | goroutine, channel, select |
| Parallelism | Aufgaben gleichzeitig ausführen | GOMAXPROCS, mehrere Kerne |
| Synchronisation | Gemeinsame Daten schützen | sync.Mutex, sync/atomic |
| Abbruch | Arbeit rechtzeitig stoppen | context.Context |
Was ist ein Channel und wie unterscheiden sich gepufferte und ungepufferte Channels?
Ein Channel ist eine typisierte Leitung, die Werte zwischen Goroutines transportiert. Effective Go fasst die Idee so zusammen: Kommunizieren Sie nicht, indem Sie Speicher teilen; teilen Sie stattdessen Speicher, indem Sie kommunizieren. Anders gesagt übergeben Sie das Eigentum an Daten über einen Channel, statt die Daten mit einem Lock zu schützen.
ch := make(chan int) // ungepuffert
bch := make(chan int, 3) // gepuffert, Kapazität 3
Bei einem ungepufferten Channel wartet der Sender, bis ein Empfänger bereit ist. Senden und Empfangen passieren also gemeinsam, und beide Goroutines synchronisieren sich. Bei einem gepufferten Channel wartet der Sender erst, wenn der Puffer voll ist. Dann blockiert er allerdings ebenfalls.
Eine typische Falle folgt: Löst ein Puffer einen Deadlock? Meistens nicht, er verschiebt ihn nur. Deshalb sollten Sie sagen, dass Sie die Puffergröße nach dem Design wählen und nicht nach Geschwindigkeit. Diese Antwort hinterlässt meist einen guten Eindruck.
Was passiert beim Lesen oder Schreiben auf einem geschlossenen Channel?
Lesen aus einem geschlossenen Channel löst keine Panic aus. Sobald die gepufferten Werte aufgebraucht sind, erhalten Sie den Nullwert des Typs. Schreiben in einen geschlossenen Channel führt dagegen zu einer Panic. Auch doppeltes Schließen desselben Channels endet in einer Panic. Nach diesen drei Verhaltensweisen fragen Interviewer fast immer.
v, ok := <-ch
if !ok {
// Channel geschlossen und leer
}
Der zweite Rückgabewert ok verrät, ob der Wert aus einem echten Senden stammt oder aus dem Schließen. Außerdem endet eine range Schleife über einen Channel von selbst, sobald dieser geschlossen und leer ist. Daher sollte der Erzeuger den Channel schließen, wenn seine Arbeit fertig ist.
Die Faustregel lautet: Nur der Sender schließt einen Channel, nie der Empfänger. Gibt es mehrere Sender, übernimmt eine eigene Goroutine das Schließen und koordiniert es mit einer WaitGroup. Dieses Vorgehen sehen Sie zum Beispiel beim Fan In Muster.
Wie verhält sich ein nil Channel und warum hilft er in select?
Senden an einen nil Channel blockiert für immer, Empfangen ebenso. Auf den ersten Blick wirkt das wie ein Fehler. In der Praxis ist es allerdings eine bewusste Technik innerhalb von select. Wollen Sie einen Zweig abschalten, setzen Sie die Channel Variable auf nil, und select wählt diesen Zweig nicht mehr.
for a != nil || b != nil {
select {
case v, ok := <-a:
if !ok { a = nil; continue }
fmt.Println(v)
case v, ok := <-b:
if !ok { b = nil; continue }
fmt.Println(v)
}
}
In diesem Beispiel können zwei Quellen unabhängig voneinander schließen. Setzen Sie die geschlossene Quelle auf nil, liest die Schleife weiter aus der anderen. Somit halten Nullwerte aus einem geschlossenen Channel die Schleife nicht beschäftigt. Wer diese Frage sauber beantwortet, hat meist schon echten Code mit Channels geschrieben.
Wie funktioniert select und wofür dient der default Zweig?
Select wartet gleichzeitig auf mehrere Channel Operationen und führt einen der bereiten Zweige aus. Sind mehrere Zweige bereit, wählt Go zufällig, also dürfen Sie sich nicht auf eine Reihenfolge verlassen. Ist kein Zweig bereit und fehlt default, blockiert select.
select {
case msg := <-eingang:
verarbeite(msg)
case <-time.After(2 * time.Second):
log.Println("Timeout")
}
Mit default versuchen Sie eine Operation, ohne zu warten. Ein Logschreiber kann zum Beispiel eine Nachricht verwerfen, wenn sein Puffer voll ist. Setzen Sie default allerdings in eine for Schleife, entsteht eine Schleife im Leerlauf, die unnötig CPU verbraucht. Genau diesen Fehler suchen Interviewer gezielt.
In lange laufenden Schleifen erwarten sie zudem einen wiederverwendeten time.Timer statt time.After in jeder Runde. So erzeugen Sie nicht bei jedem Durchlauf einen neuen Timer.
Wann nutzen Sie eine WaitGroup und wann einen Mutex?
Mit einer WaitGroup warten Sie darauf, dass eine Gruppe von Goroutines fertig ist. Ein Mutex sorgt dagegen dafür, dass jeweils nur eine Goroutine auf gemeinsame Daten zugreift. Kurz gesagt beantwortet die WaitGroup die Frage „wann ist es fertig“ und der Mutex die Frage „wer darf zugreifen“.
var wg sync.WaitGroup
var mu sync.Mutex
summe := 0
for i := 1; i <= 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
mu.Lock()
summe += i
mu.Unlock()
}()
}
wg.Wait()
Laut den Release Notes zu Go 1.25 hat WaitGroup eine neue Methode Go erhalten. Sie fasst das Starten und Zählen von Goroutines in einem Aufruf zusammen. Arbeitet das Team mit einer aktuellen Version, bringt dieses Wissen Pluspunkte. Trotzdem sollten Sie das ältere Muster erklären können, denn die meisten bestehenden Codebasen nutzen Add und Done.
Ein klassischer Fehler: wg.Add innerhalb der Goroutine aufrufen. Dann läuft Wait unter Umständen vor Add, und das Programm endet zu früh.
Wann sind RWMutex oder sync/atomic die bessere Wahl?
RWMutex passt, wenn Lesezugriffe deutlich häufiger sind als Schreibzugriffe. Mehrere Leser halten das Lock gleichzeitig, ein Schreiber hält es allein. Das Paket sync/atomic aktualisiert dagegen einfache Werte wie einen Zähler oder ein Flag sicher und ohne Lock.
Allerdings ist RWMutex nicht bei jeder leselastigen Struktur automatisch schneller. Ist der kritische Abschnitt sehr kurz, kann der Zusatzaufwand teurer sein als ein einfacher Mutex. Deshalb ist im Interview diese Antwort richtig: „Ohne Messung entscheide ich nicht, ich schreibe einen Benchmark.“
- Einzelner Zähler oder Flag: atomic.Int64 oder atomic.Bool.
- Struktur mit mehreren Feldern, die sich gemeinsam ändern: sync.Mutex.
- Viele Lesezugriffe, seltene Schreibzugriffe und langer kritischer Abschnitt: sync.RWMutex.
- Einmalige Initialisierung: sync.Once.
Was ist ein Data Race und wie finden Sie ihn mit dem Race Detector?
Ein Data Race entsteht, wenn zwei Goroutines gleichzeitig auf dieselbe Speicherstelle zugreifen, mindestens eine davon schreibt und keine Synchronisation dazwischen liegt. Das Go Speichermodell stellt klar, dass sich Programme mit Races unvorhersehbar verhalten können. Daher ist „bei mir läuft es“ keine Antwort.
go test -race ./...
go run -race main.go
Der Race Detector beobachtet Speicherzugriffe in einem Programm, das Sie mit dem Flag -race bauen, und meldet Races mit Stacktraces. Allerdings sieht er nur Codepfade, die tatsächlich laufen. Einen Race auf einem Pfad, den Ihre Tests nie erreichen, findet er nicht. Deshalb empfehle ich, die Tests in der CI mit -race auszuführen.
Laut Dokumentation erhöht der Race Detector Speicherbedarf und Laufzeit spürbar. Sie lassen ihn also nicht dauerhaft in Produktion laufen, sondern nutzen ihn in Lasttests und in der CI. Wer diese Abwägung erklärt, zeigt, dass er das Werkzeug wirklich kennt.
Wie entstehen Deadlocks und wie verhindern Sie sie?
Ein Deadlock entsteht, wenn Goroutines aufeinander warten und keine weiterkommt. Blockieren alle Goroutines, stoppt die Go Laufzeit das Programm mit „all goroutines are asleep - deadlock!“. Blockiert allerdings nur ein Teil, läuft das Programm weiter, und das Problem wächst unbemerkt.
func main() {
ch := make(chan int)
ch <- 1 // kein Empfänger, wartet ewig
fmt.Println(<-ch)
}
Ein paar Regeln helfen. Zunächst nehmen Sie Locks immer in derselben Reihenfolge. Außerdem versehen Sie Channel Operationen mit Timeout oder context, damit nichts ewig wartet. Schließlich vermeiden Sie Aufrufe von fremdem Code, solange Sie ein Lock halten. Ein Senden auf einen Channel innerhalb eines gesperrten Abschnitts ist zum Beispiel eine klassische Deadlock Quelle.
Was ist ein Goroutine Leak und wie erkennen Sie ihn?
Ein Goroutine Leak ist eine Ansammlung von Goroutines, die nie enden, obwohl ihre Arbeit erledigt ist. Die übliche Ursache: Eine Goroutine will auf einen Channel senden, den niemand liest, oder wartet auf einen Channel, der nie schließt. Folglich steigt der Speicherbedarf langsam, und der Dienst wird Tage später langsamer.
func ersteAntwort(urls []string) string {
ch := make(chan string, len(urls)) // Puffer verhindert das Leak
for _, u := range urls {
go func() { ch <- hole(u) }()
}
return <-ch
}
Ohne Puffer würden die übrigen Goroutines nach der ersten Antwort für immer blockieren. Zur Erkennung beobachten Sie runtime.NumGoroutine als Metrik und erstellen mit pprof ein Goroutine Profil. Zudem können Sie in Tests prüfen, ob die Zahl der Goroutines am Ende wieder beim Startwert liegt.
Die Geschwindigkeit eines Dienstes hängt nicht nur vom Backend ab. Das Tempo, das Nutzer im Frontend spüren, hängt direkt mit der Frage zusammen, wie die Ladezeit SEO beeinflusst.
Wie steuert das Paket context Abbruch und Timeouts?
Ein context transportiert ein Abbruchsignal, eine Frist und anfragebezogene Werte über Goroutines hinweg. Bricht ein Client eine HTTP Anfrage ab, stoppen die zugehörige Datenbankabfrage und der externe API Aufruf mit demselben Signal. Somit arbeitet keine Goroutine umsonst weiter.
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel()
select {
case erg := <-verarbeite(ctx):
schreibe(w, erg)
case <-ctx.Done():
http.Error(w, ctx.Err().Error(), http.StatusGatewayTimeout)
}
Der Interviewer achtet hier auf drei Details. Erstens müssen Sie cancel aufrufen, meist mit defer; sonst entstehen Ressourcenlecks. Zweitens übergeben Sie context als ersten Parameter und nicht als Feld einer Struktur. Drittens nutzen Sie WithValue für anfragebezogene Daten wie eine Trace ID und nicht für optionale Parameter.
Wie bauen Sie einen Worker Pool in Go?
Ein Worker Pool besteht aus einer festen Zahl von Goroutines, die Aufträge aus einer gemeinsamen Warteschlange ziehen. Das Ziel: die Nebenläufigkeit begrenzen, damit externe Ressourcen wie Datenbankverbindungen nicht überlaufen. Diese Aufgabe gehört zu den häufigsten beim Live Coding.
func pool(jobs <-chan int, n int) <-chan int {
aus := make(chan int)
var wg sync.WaitGroup
for w := 0; w < n; w++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := range jobs {
aus <- j * j
}
}()
}
go func() { wg.Wait(); close(aus) }()
return aus
}
Beachten Sie, dass eine eigene Goroutine den Channel aus schließt. Das passiert erst, wenn alle Worker fertig sind, deshalb kann der Verbraucher mit range sicher lesen. Außerdem lassen gerichtete Channel Typen wie <-chan und chan<- den Compiler Fehlbenutzung erkennen.
Was sind Fan Out, Fan In und Pipeline Muster?
Eine Pipeline ist eine Kette von Stufen, die Channels verbinden. Fan Out verteilt eine Stufe auf mehrere Goroutines. Fan In führt mehrere Channels zu einem zusammen. Interviewer fragen diese drei Muster meist gemeinsam ab.
Denken Sie an einen Bilddienst mit drei Stufen: Dateien lesen, verkleinern und speichern. Ist das Verkleinern der langsamste Schritt, verteilen Sie ihn per Fan Out auf vier Worker und sammeln die Ergebnisse per Fan In in einem Channel. So erweitern Sie den Engpass nur dort, wo es nötig ist.
- Jede Stufe nimmt einen Eingangs Channel und gibt einen Ausgangs Channel zurück.
- Die Stufe schließt ihren Ausgang, sobald ihre Arbeit fertig ist.
- Alle Stufen hören auf context und steigen beim Abbruch früh aus.
- Fan In koordiniert das Schließen mit einer WaitGroup.
Zeigen Sie diese Liste in Code, folgt meist die Nachfrage: Warum entsteht bei einer abgebrochenen Pipeline kein Leak?
Wie helfen errgroup und Semaphoren bei der Fehlerbehandlung?
Das Paket errgroup liegt in golang.org/x/sync. Es startet eine Gruppe von Goroutines und liefert den ersten Fehler zurück. Erstellen Sie es mit WithContext, bricht ein fehlerhafter Aufruf den gemeinsamen context ab, und die anderen stoppen ebenfalls. Anders gesagt erhalten Sie WaitGroup, Fehlerbehandlung und Abbruch in einem Paket.
g, ctx := errgroup.WithContext(ctx)
g.SetLimit(5)
for _, u := range urls {
g.Go(func() error { return lade(ctx, u) })
}
if err := g.Wait(); err != nil {
return err
}
SetLimit begrenzt, wie viele Goroutines gleichzeitig laufen. Daher brauchen Sie in einfachen Fällen keine eigene Semaphore. Brauchen Sie allerdings gewichtete Ressourcenteilung, greifen Sie zum Paket semaphore im selben Modul. Wer beide Werkzeuge unterscheidet, zeigt Erfahrung mit echtem Servicecode.
Wie hat sich die Falle mit der Schleifenvariable in Go 1.22 geändert?
Vor Go 1.22 war die Variable einer for Schleife eine einzige Variable für alle Durchläufe. Eine Goroutine, die sie einfing, gab deshalb oft den letzten Wert aus. Laut dem Go Blog erhält seit Go 1.22 jeder Durchlauf eine eigene Variable, und dieser klassische Fehler verschwindet.
for _, v := range []string{"a", "b", "c"} {
go func() { fmt.Println(v) }() // ab Go 1.22: a, b, c
}
Trotzdem kann der Interviewer nach dem alten Verhalten fragen. Module, deren go.mod eine ältere Go Version angibt, behalten nämlich die alte Semantik. Eine gute Antwort nennt die neue Regel und erklärt, warum älterer Code Zeilen wie v := v enthält.
Solche Versionsdetails zählen in Teams, die regelmäßig aktualisieren. In meinen eigenen Projekten plane ich Upgrades genauso, und für das Frontend habe ich diese Disziplin im Beitrag über Micro Frontends beschrieben.
Warum ist GOMAXPROCS in Containern wichtig?
GOMAXPROCS legt fest, wie viele P gleichzeitig Go Code ausführen. Lange entsprach der Standardwert der Zahl logischer CPUs der Maschine. In Kubernetes konnte das einen Wert weit über dem CPU Limit des Containers bedeuten, was unnötiges Drosseln verursachte.
Laut den Release Notes zu Go 1.25 berücksichtigt die Laufzeit unter Linux nun das CPU Bandbreitenlimit der cgroup. Liegt dieses Limit unter der Zahl logischer CPUs, sinkt GOMAXPROCS standardmäßig auf das Limit. Zudem aktualisiert die Laufzeit den Wert regelmäßig. Setzen Sie GOMAXPROCS allerdings von Hand, schaltet sich dieses Verhalten ab.
Fragen Sie in Ihrer Antwort ruhig nach der Go Version des Dienstes, denn das allein zeigt Reife. Bei einer älteren Version ist es richtig zu sagen, dass Sie den Wert manuell setzen würden.
Wie testen Sie nebenläufigen Go Code?
Sie stützen sich auf drei Werkzeuge: das Flag -race, Tests mit Timeout und deterministische Zeit. Das Paket testing/synctest ist seit Go 1.25 allgemein verfügbar und führt einen Test in einer isolierten Blase aus, in der die Zeit virtuell läuft. Folglich enden Tests mit time.Sleep sofort.
Verlassen Sie sich außerdem auf Synchronisationspunkte statt auf Wartezeiten. Nutzen Sie zum Beispiel ein Signal über einen Channel, um den Start einer Goroutine zu erkennen, und kein Sleep. Diese kleine Änderung beseitigt die meisten wackeligen Tests in der CI.
- Jeden Test mindestens einmal mit go test -race ausführen.
- Wackelige Tests mit dem Flag -count mehrfach laufen lassen.
- Für zeitabhängige Logik synctest oder eine injizierbare Uhr nutzen.
- Prüfen, ob die Zahl der Goroutines am Ende zum Startwert zurückkehrt.
Leistung beurteilen Sie nie ohne Messung. Dasselbe gilt für Websites, wie ich im Leitfaden zum Lighthouse Test erkläre.
Welche Aufgaben kommen in der Live Coding Runde?
In der Live Coding Runde kommen meist kleine Aufgaben von 30 bis 45 Minuten; diese Spanne ist meine eigene Beobachtung und keine Garantie. Am häufigsten sehe ich: URLs mit begrenzter Nebenläufigkeit laden, Anfragen mit Timeout bündeln und einen threadsicheren Cache schreiben.
- Die Aufgabe in eigenen Worten wiederholen und nach Grenzen fragen.
- Zuerst die einfachste lauffähige Version schreiben.
- Danach Nebenläufigkeit ergänzen und den Abbruchpfad zeigen.
- Zum Schluss Risiken für Races und Leaks laut bewerten.
Folgen Sie dieser Reihenfolge, bleibt lauffähiger Code übrig, auch wenn die Zeit abläuft. Wer dagegen sofort zu einer raffinierten Lösung springt, endet oft mit halbfertigem Code. Kurz gesagt bewertet der Interviewer Ihr Denken stärker als perfekten Code.
Wie planen Sie die Vorbereitung auf Golang Interview Fragen?
Für Golang Interview Fragen ist ein Plan über zwei Wochen für die meisten Kandidaten ein fairer Start; das ist eine Empfehlung aus der Praxis, keine Garantie. In der ersten Woche lernen Sie Sprachgrundlagen und Konzepte der Nebenläufigkeit. Dann folgen in der zweiten Woche Muster und Live Coding.
| Tage | Thema | Ergebnis |
|---|---|---|
| 1 bis 3 | Slices, Maps, Interfaces, Fehler | Ein kleines CLI Tool |
| 4 bis 7 | Goroutines, Channels, select, sync | Ein Zähler mit Race und seine Korrektur |
| 8 bis 10 | context, Worker Pool, errgroup | Ein begrenzter nebenläufiger Downloader |
| 11 bis 14 | Tests, Race Detector, pprof, Probeinterview | Ein kleiner getesteter Dienst |
Legen Sie jedes Ergebnis in einem GitHub Repository ab, dann haben Sie ein echtes Portfolio. Außerdem belegen saubere README Dateien Ihre schriftliche Kommunikation. Brauchen Sie Hilfe bei der Seite eines Projekts jenseits des Codes, sehen Sie sich mein Webdesign Angebot an.
Welche Fehler machen Kandidaten bei Golang Interview Fragen?
Der häufigste Fehler bei Golang Interview Fragen: jedes Problem mit Channels lösen wollen. Manchmal ist ein einfacher Mutex lesbarer und schneller. Die Go Dokumentation stellt beide Werkzeuge als Partner dar, nicht als Rivalen. Daher erwartet der Interviewer eine Begründung für Ihre Wahl.
- Warten mit time.Sleep.
- Einen Channel auf der Empfängerseite schließen.
- Den Aufruf von cancel vergessen.
- Unbegrenzt Goroutines starten und Ressourcen erschöpfen.
- Den Race Detector nie benutzt haben.
Ein weiterer Fehler ist das Verschlucken von Fehlern. Statt einen Fehler in der Goroutine nur zu loggen, reichen Sie ihn über errgroup oder einen Ergebnis Channel nach oben weiter. Fragt der Interviewer, wohin der Fehler geht, brauchen Sie eine klare Antwort.
Bereiten Sie schließlich Lebenslauf und Portfolioseite sorgfältig vor. Auf meiner Seite über mich beschreibe ich offen, wie ich arbeite, und ich rate Ihnen zu derselben Offenheit. Bei Fragen erreichen Sie mich über die Kontaktseite.
Mit welchen offiziellen Quellen sollten Sie lernen?
Die verlässlichste Quelle ist das Go Team selbst. Effective Go behandelt die Grundideen im Abschnitt zur Nebenläufigkeit. Das Go Speichermodell liefert die formale Definition der Synchronisation und ist die Quelle vieler Fragen auf Senior Niveau.
Zudem erklärt der Artikel zum Race Detector die Grenzen des Werkzeugs. Für Versionsänderungen lesen Sie die Release Notes zu Go 1.25 und den Beitrag im Go Blog zu Schleifenvariablen. So sprechen Sie im Interview mit aktuellen, prüfbaren Fakten.




