# Go Generics 2026: Typparameter, Constraints und Interview-Fragen > Dieser Artikel behandelt wichtige Go-Generics-Interview-Fragen für 2026, von grundlegenden Typparametern bis hin zu fortgeschrittenen Constraint-Mustern. - Published: 2026-07-08 - Updated: 2026-07-08 - Author: SharpSkill - Reading time: 5 min --- Go 1.18 führte im März 2022 Generics in die Sprache ein, und seitdem hat sich diese Funktion durch Go 1.21, 1.22 und darüber hinaus weiterentwickelt. Dieser Artikel behandelt wichtige Go-Generics-Interview-Fragen für 2026, von grundlegenden Typparametern bis hin zu fortgeschrittenen Constraint-Mustern, die in technischen Vorstellungsgesprächen häufig vorkommen. > **Was sind Go Generics?** > > Go Generics ermöglichen das Schreiben von Funktionen und Typen, die mit beliebigen Datentypen arbeiten und dabei die Typsicherheit zur Compile-Zeit gewährleisten. Im Gegensatz zu Interfaces, die Runtime-Type-Assertions verwenden, werden bei Generics die Typen zur Compile-Zeit aufgelöst, was bessere Performance und frühere Fehlererkennung bietet. ## Typparameter in Go verstehen Typparameter bilden die Grundlage von Go Generics. Ein Typparameter ist ein Platzhalter für einen Typ, der beim Verwenden der generischen Funktion oder des generischen Typs spezifiziert wird. ```go // generic.go // Basic generic function with type parameter T func PrintSlice[T any](items []T) { for _, item := range items { fmt.Println(item) } } // Usage - type inference determines T automatically func main() { PrintSlice([]int{1, 2, 3}) // T is int PrintSlice([]string{"a", "b"}) // T is string } ``` Die Syntax mit eckigen Klammern `[T any]` deklariert einen Typparameter `T`, der durch `any` eingeschränkt ist. Der Go-Compiler leitet den konkreten Typ aus den Argumenten ab, wodurch in den meisten Fällen keine explizite Typangabe erforderlich ist. ## Häufige Interview-Frage: Was ist der Unterschied zwischen `any` und `comparable`? Interviewer fragen häufig nach den eingebauten Constraints `any` und `comparable`. Das Verständnis ihrer Unterschiede demonstriert solides Generics-Wissen. ```go // constraints.go // any: accepts all types (alias for interface{}) func Process[T any](value T) T { return value } // comparable: only types that support == and != func Contains[T comparable](slice []T, target T) bool { for _, v := range slice { if v == target { // This comparison requires comparable return true } } return false } // This compiles Contains([]int{1, 2, 3}, 2) // This fails: slices are not comparable // Contains([][]int{{1}, {2}}, []int{1}) ``` Das `comparable`-Constraint beschränkt Typparameter auf Typen, die Gleichheitsoperatoren unterstützen. Slices, Maps und Funktionen sind ausgeschlossen, da Go für diese auf Sprachebene keine Gleichheit definiert. ## Benutzerdefinierte Typconstraints mit Interfaces erstellen Go verwendet Interfaces zur Definition benutzerdefinierter Constraints und erweitert damit, was generische Funktionen akzeptieren können. Die [Go-Spezifikation](https://go.dev/ref/spec#Type_constraints) definiert, wie Typelemente innerhalb von Constraint-Interfaces funktionieren. ```go // number.go // Custom constraint using type union type Number interface { int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 } // Generic function constrained to numeric types func Sum[T Number](values []T) T { var total T for _, v := range values { total += v // + operator works because all Number types support it } return total } func main() { fmt.Println(Sum([]int{1, 2, 3})) // 6 fmt.Println(Sum([]float64{1.5, 2.5})) // 4.0 } ``` Typvereinigungen mit `|` spezifizieren, welche exakten Typen das Constraint erfüllen. Dieser Ansatz bietet mehr Kontrolle als `any` und vermeidet gleichzeitig Runtime-Type-Assertions. ## Interview-Frage: Den `~` Tilde-Operator in Constraints erklären Der Tilde-Operator `~` in Constraints erfasst sowohl einen Typ als auch alle Typen mit diesem zugrunde liegenden Typ. Diese Frage testet das Verständnis von Gos Typsystem. ```go // underlying.go // ~int matches int and any type with int as underlying type type Signed interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 } // Custom type with int as underlying type type UserID int type Temperature int64 func Abs[T Signed](value T) T { if value < 0 { return -value } return value } func main() { var id UserID = -42 var temp Temperature = -10 fmt.Println(Abs(id)) // 42 - works because ~int matches UserID fmt.Println(Abs(temp)) // 10 - works because ~int64 matches Temperature } ``` Ohne `~` würde das Constraint `int` nur den exakten Typ `int` erfassen, nicht benutzerdefinierte Typen wie `UserID`. Die Tilde erweitert das Constraint um abgeleitete Typen und macht generischen Code flexibler. ## Generische Typen: Structs und Methoden Generische Typen gehen über Funktionen hinaus zu Structs und Methoden. Dieses Muster erscheint häufig in Datenstruktur-Implementierungen. ```go // stack.go // Generic Stack type type Stack[T any] struct { items []T } // Push adds an element to the stack func (s *Stack[T]) Push(item T) { s.items = append(s.items, item) } // Pop removes and returns the top element func (s *Stack[T]) Pop() (T, bool) { if len(s.items) == 0 { var zero T // Zero value for type T return zero, false } index := len(s.items) - 1 item := s.items[index] s.items = s.items[:index] return item, true } func main() { intStack := Stack[int]{} intStack.Push(10) intStack.Push(20) val, ok := intStack.Pop() // val=20, ok=true } ``` Zu beachten ist, dass Methoden auf generischen Typen den Typparameter in Klammern wiederholen müssen, aber keine neuen Typparameter einführen können. Der Receiver `(s *Stack[T])` bindet die Methode an die spezifische Instanziierung von `Stack`. ## Interview-Frage: Warum können Methoden keine eigenen Typparameter haben? Go verbietet zusätzliche Typparameter bei Methoden, eine Designentscheidung, die Entwickler überrascht, die von Sprachen wie Java oder C# kommen. Der [Go Generics Proposal](https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md) erklärt, dass diese Einschränkung existiert, um das Typsystem handhabbar zu halten. ```go // This is NOT valid Go code type Container[T any] struct { value T } // ERROR: methods cannot have type parameters // func (c *Container[T]) Transform[U any](fn func(T) U) U { // return fn(c.value) // } // Valid alternative: use a standalone function func Transform[T, U any](c *Container[T], fn func(T) U) U { return fn(c.value) } ``` Die Lösung verwendet Top-Level-Funktionen mit mehreren Typparametern anstelle von Methoden. Dieses Design hält den Method-Dispatch einfach und vermeidet komplexe Interaktionen zwischen Receiver-Typen und Methoden-Typparametern. ## Typinferenz und Constraint-Inferenz Gos Typinferenz reduziert die Ausführlichkeit beim Aufrufen generischer Funktionen. Das Verständnis, wann explizite Typargumente erforderlich sind, hilft beim Schreiben saubereren Codes. ```go // inference.go func Map[T, R any](input []T, transform func(T) R) []R { result := make([]R, len(input)) for i, v := range input { result[i] = transform(v) } return result } func main() { numbers := []int{1, 2, 3} // Type inference: T=int, R=string inferred from arguments strings := Map(numbers, func(n int) string { return fmt.Sprintf("%d", n) }) // Explicit types sometimes required for complex cases // Map[int, string](numbers, converter) } ``` Die Typinferenz arbeitet von Funktionsargumenten zu Typparametern. Wenn der Compiler Typen nicht allein aus den Argumenten ableiten kann, lösen explizite Typargumente in eckigen Klammern die Mehrdeutigkeit auf. ## Constraints-Paket: `cmp` und `slices` in der Standardbibliothek Go 1.21 fügte das `cmp`-Paket mit dem `Ordered`-Constraint und Vergleichsfunktionen hinzu. Das `slices`-Paket demonstriert idiomatischen generischen Code in der Standardbibliothek. ```go // stdlib.go import ( "cmp" "slices" ) func main() { numbers := []int{3, 1, 4, 1, 5, 9} // slices.Sort uses cmp.Ordered constraint internally slices.Sort(numbers) // [1, 1, 3, 4, 5, 9] // Binary search on sorted slice index, found := slices.BinarySearch(numbers, 4) // cmp.Compare returns -1, 0, or 1 result := cmp.Compare(3, 5) // -1 // cmp.Or returns first non-zero value value := cmp.Or(0, 0, 42, 100) // 42 } ``` Die [Standardbibliothek-Dokumentation](https://pkg.go.dev/cmp) zeigt, wie diese Pakete Generics für typsichere Operationen auf geordneten Typen nutzen. Vertrautheit mit diesen Paketen demonstriert praktisches Generics-Wissen jenseits des theoretischen Verständnisses. ## Interview-Frage: Implementierung eines generischen Caches Eine häufige Interview-Übung fordert Kandidaten auf, einen generischen, thread-sicheren Cache zu implementieren. Dies testet Generics, Nebenläufigkeit mit dem [sync-Paket](/technologies/go/interview-questions/sync-primitives) und API-Design. ```go // cache.go import ( "sync" "time" ) type Cache[K comparable, V any] struct { mu sync.RWMutex items map[K]cacheItem[V] } type cacheItem[V any] struct { value V expiration time.Time } func NewCache[K comparable, V any]() *Cache[K, V] { return &Cache[K, V]{ items: make(map[K]cacheItem[V]), } } func (c *Cache[K, V]) Set(key K, value V, ttl time.Duration) { c.mu.Lock() defer c.mu.Unlock() c.items[key] = cacheItem[V]{ value: value, expiration: time.Now().Add(ttl), } } func (c *Cache[K, V]) Get(key K) (V, bool) { c.mu.RLock() defer c.mu.RUnlock() item, exists := c.items[key] if !exists || time.Now().After(item.expiration) { var zero V return zero, false } return item.value, true } ``` Diese Implementierung verwendet `comparable` für Keys (Map-Anforderung) und `any` für Values. Das separate `cacheItem`-Struct zeigt, wie generische Typen ineinander verschachtelt werden können. Thread-Sicherheit kommt von `sync.RWMutex`, ein Muster, das in Go-[Nebenläufigkeits-Interviews](/technologies/go/interview-questions/concurrency-patterns) behandelt wird. ## Nullwerte und Typconstraints Der Umgang mit Nullwerten in generischem Code erfordert das Verständnis, wie Go Variablen parametrisierter Typen initialisiert. ```go // zero.go // Return zero value when slice is empty func First[T any](slice []T) T { if len(slice) == 0 { var zero T // Zero value: 0 for int, "" for string, nil for pointers return zero } return slice[0] } // Alternative: return pointer to avoid ambiguity func FirstOrNil[T any](slice []T) *T { if len(slice) == 0 { return nil } return &slice[0] } ``` Das `var zero T`-Muster erstellt einen Nullwert für jeden Typ `T`. Für Typen, bei denen Null ein gültiger Wert ist (wie `0` für Integer), unterscheidet die Pointer-zurückgebende Variante zwischen "nicht gefunden" und "Null gefunden". ## Fortgeschritten: Mehrere Constraints kombinieren Komplexe generische Funktionen können erfordern, dass Typen mehrere Constraints erfüllen. Go handhabt dies durch Interface-Einbettung. ```go // combined.go // Constraint requiring both ordering and string conversion type Stringable interface { String() string } type OrderedStringable interface { cmp.Ordered Stringable } // Alternative: use type parameters with multiple constraints inline func PrintSorted[T interface{ cmp.Ordered; fmt.Stringer }](items []T) { slices.Sort(items) for _, item := range items { fmt.Println(item.String()) } } ``` Interface-Einbettung kombiniert Constraints und erfordert, dass Typen alle eingebetteten Interfaces implementieren. Die Inline-Syntax `interface{ A; B }` bietet die gleiche Funktionalität ohne Deklaration eines benannten Constraint-Typs. ## Fazit - Typparameter mit `[T any]` ermöglichen das Schreiben von wiederverwendbarem, typsicherem Code ohne Runtime-Reflection - `comparable` beschränkt auf Typen, die `==` und `!=` unterstützen, erforderlich für Map-Keys - Die `~`-Tilde erfasst Typen mit einem spezifischen zugrunde liegenden Typ und erweitert die Constraint-Flexibilität - Benutzerdefinierte Constraints verwenden Typvereinigungen (`int | string`) zur Spezifikation exakt erlaubter Typen - Methoden können keine eigenen Typparameter haben; Top-Level-Funktionen dienen als Alternative - Die Standardbibliothek-Pakete `cmp` und `slices` demonstrieren idiomatische generische Muster - Nullwerte über `var zero T` behandeln leere oder fehlende Daten in generischen Funktionen - Thread-sichere generische Datenstrukturen kombinieren Generics mit sync-Primitiven --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/de/blog/go/go-generics-type-parameters-constraints-interview-questions