Wie man ein Go-Vorstellungsgespräch besteht: Top-Fragen
Go (Golang) ist eine der gefragtesten Sprachen für die Entwicklung hochlastiger Serveranwendungen und Microservices. Ein Vorstellungsgespräch für eine Go-Entwicklerposition testet oft nicht nur die Kenntnis der Syntax, sondern auch das Verständnis der internen Funktionsweise: Goroutinen, Channels, Interfaces und Speicherverwaltung. In diesem Artikel analysieren wir die Top-10-Fragen, die in Vorstellungsgesprächen am häufigsten gestellt werden, mit Codebeispielen und Erklärungen.
1. Was ist der Unterschied zwischen einem Array und einem Slice (array vs slice)?
Dies ist eine klassische Frage zum Verständnis der Go-Grundlagen.
- Array — ist eine feste Sequenz von Elementen desselben Typs. Die Größe des Arrays ist Teil seines Typs.
- Slice — ist eine dynamische Struktur, die auf ein zugrunde liegendes Array verweist. Ein Slice kann wachsen und seine Größe ändern.
// Array — feste Größevar arr [3]int = [3]int{1, 2, 3}// Slice — dynamischvar slc []int = []int{1, 2, 3}
// Wichtig: arr und [4]int sind unterschiedliche Typen// Slices werden als Referenz übergeben (Pointer auf underlying array)Tipp: Wenn Sie die Länge ändern müssen, verwenden Sie einen Slice. Wenn eine garantierte feste Größe benötigt wird, verwenden Sie ein Array.
2. Was sind Goroutinen und wie funktionieren sie?
Eine Goroutine ist ein leichter Ausführungsfaden, der von der Go-Laufzeitumgebung verwaltet wird. Im Gegensatz zu System-Threads (OS threads) haben Goroutinen einen kleineren Stack (ab 2 KB) und wechseln schnell.
- Starten einer Goroutine:
go func() - Goroutinen arbeiten im selben Adressraum, daher muss der Zugriff auf gemeinsame Daten synchronisiert werden (über Channels oder Mutexe).
package main
import ( "fmt" "time")
func printNumbers() { for i := 1; i <= 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(i) }}
func main() { go printNumbers() // Goroutine starten time.Sleep(1 * time.Second) // auf Fertigstellung warten fmt.Println("Main done")}Wichtig: Die Hauptfunktion wartet nicht auf die Fertigstellung von Goroutinen. Verwenden Sie zur Synchronisation sync.WaitGroup oder Channels.
3. Wie funktionieren Channels?
Channels sind typisierte "Röhren", über die Goroutinen Daten austauschen. Sie ermöglichen eine sichere Datenübertragung ohne explizite Sperren.
- Ungepufferter Channel: Der Sender wird blockiert, bis der Empfänger die Daten liest.
- Gepufferter Channel: Der Sender wird nur blockiert, wenn der Puffer voll ist.
ch := make(chan int) // ungepuffertchBuf := make(chan int, 3) // gepuffert (Kapazität 3)
// Sendengo func() { ch <- 42}()
// Empfangenvalue := <-chfmt.Println(value)
// Channel schließenclose(ch)// Lesen aus einem geschlossenen Channel gibt den zero value zurückHäufige Frage: Was passiert, wenn man aus einem nil-Channel liest? — Antwort: Die Goroutine blockiert für immer (deadlock).
4. Was sind Interfaces in Go und wie unterscheiden sie sich von anderen Sprachen?
Ein Interface in Go ist eine Sammlung von Methoden. Im Gegensatz zu Java oder C# ist die Implementierung eines Interfaces in Go implizit (duck typing): Ein Typ erfüllt automatisch ein Interface, wenn er alle seine Methoden implementiert.
type Speaker interface { Speak() string}
type Dog struct{}func (d Dog) Speak() string { return "Woof!" }
type Cat struct{}func (c Cat) Speak() string { return "Meow!" }
func makeSound(s Speaker) { fmt.Println(s.Speak())}
func main() { makeSound(Dog{}) // Woof! makeSound(Cat{}) // Meow!}Warum ist das wichtig: Es ermöglicht das Schreiben von flexiblem, lose gekoppeltem Code. Das leere Interface interface{} (oder any in Go 1.18+) kann einen Wert jeden Typs speichern.