🪟 Windows TippsBitLocker stuck on Decrypting or Encrypting in Windows 11(17.09.2026 um 00:29 Uhr)
🕵️ SicherheitslückenCVE-2026-69110 | Microck opencode-studio up to 2.4.3 missing authentication(17.09.2026 um 03:21 Uhr)
🪟 Windows TippsBitLocker stuck on Decrypting or Encrypting in Windows 11(17.09.2026 um 00:29 Uhr)
🕵️ SicherheitslückenCVE-2026-69110 | Microck opencode-studio up to 2.4.3 missing authentication(17.09.2026 um 03:21 Uhr)
🔧 Programmierung 🕛 vor 3 Monaten 6 Min Lesezeit
0

Go Generics: When to Use Them, When to Avoid Them

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

I had three repositories that looked identical. UserRepository, ProductRepository, OrderRepository: same structure, same FindByID, same List, same pagination logic. The only difference was the return type. Three copies of the same code. When Go 1.18 shipped with generics, I wanted to merge them all. What happened next taught me when generics are a good idea — and when they make the problem worse.






What generics actually do



Generics let you write code parameterized by types. Where before you had to either duplicate code for each type or use interface{} with runtime type assertions, you can now write a single implementation that works for multiple types — with compile-time checking.




CODE
// Before Go 1.18: duplication or interface{}
func ContainsInt(slice []int, val int) bool {
for _, v := range slice { if v == val { return true } }
return false
}
func ContainsString(slice []string, val string) bool {
for _, v := range slice { if v == val { return true } }
return false
}

// With generics: one implementation
func Contains[T comparable](slice []T, val T) bool {
for _, v := range slice {
if v == val {
return true
}
}
return false
}






T comparable is a constraint: T can be any type that supports ==. The compiler verifies that passed types satisfy the constraint — no runtime surprises.






Patterns where generics shine






1. Utility functions on slices and maps



This is the cleanest use case. Generic operations on collections, with no business logic:




CODE
func Filter[T any](slice []T, predicate func(T) bool) []T {
result := make([]T, 0, len(slice))
for _, v := range slice {
if predicate(v) {
result = append(result, v)
}
}
return result
}

func Map[T, U any](slice []T, transform func(T) U) []U {
result := make([]U, len(slice))
for i, v := range slice {
result[i] = transform(v)
}
return result
}

func Keys[K comparable, V any](m map[K]V) []K {
keys := make([]K, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}






At the call site, it's readable and idiomatic:




CODE
activeUsers := Filter(users, func(u User) bool { return u.Active })
emails := Map(users, func(u User) string { return u.Email })
categoryIDs := Keys(categoryMap)









2. Typed data structures



A thread-safe cache, a queue, an optional value — structures you reuse everywhere but want typed:




CODE
type Cache[K comparable, V any] struct {
mu sync.RWMutex
items map[K]cacheEntry[V]
ttl time.Duration
}

type cacheEntry[V any] struct {
value V
expires time.Time
}

func NewCache[K comparable, V any](ttl time.Duration) *Cache[K, V] {
return &Cache[K, V]{
items: make(map[K]cacheEntry[V]),
ttl: ttl,
}
}

func (c *Cache[K, V]) Set(key K, value V) {
c.mu.Lock()
defer c.mu.Unlock()
c.items[key] = cacheEntry[V]{value: value, expires: time.Now().Add(c.ttl)}
}

func (c *Cache[K, V]) Get(key K) (V, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
entry, ok := c.items[key]
if !ok || time.Now().After(entry.expires) {
var zero V
return zero, false
}
return entry.value, true
}






Without generics, this cache returns interface{} and forces a type assertion on every call. With generics, the type is known at compile time:




CODE
userCache := NewCache[int, User](5 * time.Minute)
userCache.Set(42, User{Name: "Alice"})
user, ok := userCache.Get(42) // user is a User, not an interface{}









3. Result and Option types



A common pattern to avoid null values or implicit boolean returns:




CODE
type Optional[T any] struct {
value T
present bool
}

func Some[T any](v T) Optional[T] { return Optional[T]{value: v, present: true} }
func None[T any]() Optional[T] { return Optional[T]{} }

func (o Optional[T]) Unwrap() (T, bool) { return o.value, o.present }
func (o Optional[T]) OrDefault(def T) T {
if o.present { return o.value }
return def
}









When generics make everything worse






The generic repository trap



Back to my three repositories. The idea seemed good:




CODE
type Repository[T any] struct {
db *sql.DB
table string
scan func(*sql.Rows) (T, error)
}

func (r *Repository[T]) FindByID(ctx context.Context, id int) (T, error) {
rows, err := r.db.QueryContext(ctx, "SELECT * FROM "+r.table+" WHERE id = $1", id)
// ...
return r.scan(rows)
}

func (r *Repository[T]) List(ctx context.Context) ([]T, error) {
// ...
}






In practice, it broke immediately. UserRepository needs FindByEmail. ProductRepository needs FindByCategory. OrderRepository needs FindByCustomerWithItems that does a join. The shared part — FindByID and List — represents 15% of the total code. The rest is specific. The generic factors out the 15%, complicates the 85%.




CODE
// What you end up writing anyway
type UserRepository struct {
base *Repository[User] // the generic part
db *sql.DB // for specific queries
}

// The complexity just moved somewhere else









Overly complex constraints



When generic constraints start looking like this, it's a signal:




CODE
// ❌ Too complex — use an interface instead
type Processable[T Entity, R Result, E interface{ error }] interface {
Process(context.Context, T) (R, E)
Validate(T) E
Rollback(context.Context, T) E
}

// ✅ A simple interface does the same job
type Processor interface {
Process(ctx context.Context, input any) (any, error)
}






If your generic constraint needs itself to be defined, or involves more than one type parameter with relationships between them, ordinary interfaces are almost always more readable.






When methods differ by type



Generics don't let you specialize behavior per type at runtime. If the logic differs between int and string, generics don't help — you need interfaces or two distinct functions.






The practical decision rule



Situation



Solution



Same algorithm, different types, identical logic



✅ Generics



Reusable data structure (cache, queue, optional)



✅ Generics



Behavior varies by type



✅ Interfaces



Factoring business logic that differs 85% of the time



❌ Avoid generics



Constraint with more than 2 type params



❌ Probably an interface



Need reflection or type switch



❌ Generics can't help



The key question: is the logic identical for all types, or just the structure? If it's the logic: generics. If it's the behavior: interfaces. If it's both: compose them.






Conclusion



Go generics are a measured addition to a language that already valued simplicity. They don't replace interfaces — they fill a specific blind spot: algorithms and data structures that work identically for any type.



What took me time to internalize: generics are a tool for eliminating structural code duplication, not for factoring business logic. As soon as logic starts diverging by type, you leave generics territory and enter interfaces territory — which, combined with , covers the vast majority of real-world Go architecture cases.

Vollständiger Original-Artikel
Den kompletten Beitrag mit allen Details direkt auf dev.to lesen.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Hybrid Delivery Isn't a Compromise. It's the Strategy You Were Pretending Wasn't Happening.
1 Quelle
Google Warns DMA Search Changes Could Reshape Visibility for European Businesses
1 Quelle
A stored-XSS report we couldn't quite reproduce, and hardened anyway
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Go Generics: When to Use Them, When to Avoid Them

Thematisch verwandte Begriffe: Generics, When, Them, Avoid · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...