SlideShare ist ein Scribd-Unternehmen logo
1 von 40
Downloaden Sie, um offline zu lesen
Wiederverwendung mit Typsicherheit
Generics in Go
•Frank Müller
•Oldenburg
•1965 geboren
•T-Systems International
•Enterprise Architect
•@themue
Vorstellung Frank Müller
Was sind Generics?
• Generics sind ein Feature, welches die Nutzung von
Typenvariablen ermöglicht
• Sie erleichtern die Wiederverwendung von Quelltext
• Die Typsicherheit in statischen Sprachen wird dennoch
ermöglicht
• Je nach Sprache werden generische Funktionen, Strukturen und
Interfaces ermöglicht
• Die Lesbarkeit wird durch weniger Overhead im Code erhöht
Generics in Programmiersprachen Frank Müller
Die Programmiersprache Go
• Entwicklung bei Google seit Ende 2007, erstes Release
November 2009
• Initial durch Robert Griesemer, Rob Pike und Ken Thompson
• Heute große Community
• Fokus liegt auf Geschwindigkeit, Nebenläufigkeit und Spaß
• Bis heute ist Go abwärtskompatibel
• Einsatz rund um Cloud-Native und Microservices
Die Programmiersprache Go Frank Müller
❞
Go hat das Ziel, die Sicherheit und
Geschwindigkeit einer statisch typisierten
kompilierten Sprache mit der Ausdrucksstärke
und dem Komfort einer dynamisch typisierten
interpretierten Sprache zu verbinden.
Zudem soll die Sprache für moderne,
stark skalierende Systeme
geeignet sein.
–Rob Pike
• Syntax passt auf eine HTML-Seite
• Klare und wenig mehrdeutige Struktur der Sprache
• Type Inference und Garbage Collection erlauben ein Arbeiten
ähnlich wie in vielen dynamisch typisierten Sprachen
• Nebenläufigkeit unterstützt elastische Server-Anwendungen
• Compiling ist sehr schnell, Single Binary und Cross Compiling
erleichtern die Arbeit in heterogenen Umgebungen
Was Spaß macht Frank Müller
Go vor den Generics
• Doppelter Code für unterschiedliche Typen
‣ Z.B. StringSlice, IntSlice und Float64Slice im
Package sort
• Aufgabe der Typsicherheit
‣ Einsatz des Empty Interface interface{}
Go vor den Generics Frank Müller
• Type Assertions auf Empty Interfaces
‣ Risiko von Laufzeitfehlern
• Reflection auf Empty Interfaces
‣ Niedrigere Geschwindigkeit und Risiko von Laufzeitfehlern
• Code-Generierung mit Tools wie go generate
‣ Erhöhte Build-Zeit und Code-Komplexität
Workarounds Frank Müller
Go mit Generics
• Einführung mit Version 1.18
• Einsetzbar bei Funktionen, Structs und Interfaces
• Type Constraints erlauben Eingrenzung der erlaubten Typen
• So sind einfache, abgeleitete und komplexe Typen als Type
Constraints möglich
• Vorsichtige Erweiterungen der Syntax
Go mit Generics Frank Müller
•Ein oder mehrere Typen-
Parameter
•Typen-Parameter sind any,
comparable, Type Sets oder
Type Constraints
•Spezifikation bei der Nutzung
explizit oder implizit
Funktionen mit Generics – Allgemein Frank Müller
// Type constraint for numbers, constraints is "golang.org/exp/constraints".
type Number interface {
constraints.Integer | constraints.Float | constraints.Complex
}
// Add adds any two numbers of the same type.
func Add[N Number](i, j N) N {
return i+j
}
// Usage.
explicit := Add[byte](47, 11)
implicit := Add(47.11, 8.15)
Funktionen mit Generics – Beispiel Frank Müller
•Ein oder mehrere Typen-
Parameter
•Typen-Parameter sind bei
Nutzung zu spezifizieren
•Methoden müssen in der
Typenangabe die Anzahl der
Typen-Parameter wiederholen
Structs mit Generics – Allgemein Frank Müller
// Stack defines a simple generic stack data structure.
type Stack[T any] struct {
data []T
}
func (s *Stack[T]) Push(item T) int {
s.data = append(s.data, item)
return len(s.data)
}
// Usage.
s := &Stack[string]{} // Create empty string stack.
l := s.Push("Hello, JAX") // Returns 1
Structs mit Generics – Beispiel Frank Müller
•Ein oder mehrere Typen-
Parameter
•Implementierender Typ
benötigt die gleiche Typen-
Parameter
•Methoden in der
Implementierung analog zu
struct
Interfaces mit Generics – Allgemein Frank Müller
// KeyValueStore defines the interface to store keys with their values.
type KeyValueStore[K comparable, V any] interface {
Set(key K, value V) error
Get(key K) (V, error)
Delete(key K) (V, error)
}
// Map implements KeyValueStore in-memory using a map.
type Map[K comparable, V any] struct {
store map[K]V
}
func (m *Map[K, V]) Set(key K, value V) error { ... }
...
Interfaces mit Generics – Definition Frank Müller
// StoreDatas identifies and stores a number of data in any key/value store for
// string and *Data. The key is retrieved from the data with a helper.
func StoreDatas(kvs KeyValueStore[string, *Data], datas ...*Data) error {
for _, data := range datas {
if err := kvs.Put(GetKey(data), data); err != nil { return err }
}
return nil
}
// store uses the in-memory map to store its data.
store := NewMap[string, *Data]()
// Store takes lots of data to put it into the store.
err := StoreDatas(store, lotsOfData...)
Interfaces mit Generics – Nutzung Frank Müller
Grenzen ziehen
• Eingrenzung erlaubter Typen für Typen-Parameter
• Alternative in Type Sets werden über die Pipe (|) abgebildet
• Für abgeleitete Typen wird die Tilde (~) vorangestellt
• Type Constraints können kombiniert werden
• Im Package golang.org/exp/constraints sind bereits
einige Type Constraints definiert
Type Constraints Frank Müller
// Signed permits any signed integer types.
type Signed interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
}
// Unsigned permits any unsigned integer types.
type Unsigned interface {
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}
// Integer permits any integer types. It just combines signed and unsigned
// integers.
type Integer interface {
Signed | Unsigned
}
Einfache Type Constraints Frank Müller
// Stringer is now a simple type constraint.
type Stringer interface {
String() string
}
// Scaler permits types which can scale scalable, which are type constraints too.
type Scaler[S Scalable] interface {
Scale(S) S
}
// NumberStringer permits any own number type able to return itself as string.
type NumberStringer interface {
Number
Stringer
}
Type Constraints mit Methoden Frank Müller
// Different roles in a system.
type Administrator struct { ... }
func (a *Administrator) ID() string
type User struct { ... } ...
type Guest struct { ... } ...
// Role permits one of the roles and allows to call its ID method.
type Role interface {
Administrator | User | Guest
ID() string
}
Semantische Type Constraints Frank Müller
Anwendungsformen
• Typsichere Datenstrukturen wie Listen, Queues, Stacks, Sets
oder Trees, aber auch Caches
• Allgemeine Algorithmen wie Sort, Filter, Map oder Reduce
auf Strukturen wie Slices und Maps
• Generelle Hilfsfunktionen wie Swap
Einsatzmöglichkeiten von Generics Frank Müller
// Age implements NumberStringer.
type Age uint
func (a Age) String() string { return fmt.Sprintf("%d year(s)", a) }
// Add two numbers.
func Add[N Number](i, j N) N { return i+j }
// main now uses Age and Add.
func main() {
var i, j Age = 57, 10
k := Add(i, j)
fmt.Printf("Age: %v", k) // Output: "Age: 67 year(s)"
}
Einfaches Zusammenspiel Frank Müller
// FilterMap creates a slice from of new values created by fun() where
// it also returns true.
func FilterMap[I, O any](ivs []I, fun func(I) (O, bool)) []O {
var ovs []O
for _, iv := range ivs {
if ov, ok := fun(iv); ok {
ovs = append(ovs, ov)
}
}
return ovs
}
Arbeit mit Slices Frank Müller
// CacheID is a type alias for string making the meaning clearer.
type CacheID = string
// cacheItem is an internal wrapper for a cached data.
type cacheItem[D any] struct {
eol time.Time
data D
}
// Cache stores any data with a cache ID until not used for ttl.
type Cache[D any] struct {
mu sync.Mutex
ttl time.Duration
cache map[CacheID]*cacheItem[D]
}
Ein einfacher Cache – Typen Frank Müller
// NewCache creates a cache for any D with the given time to live.
func NewCache[D any](ttl time.Duration) *Cache[D] {
c := &Cache[D]{
ttl: ttl,
cache: make(map[string]*cacheItem[D]),
}
return c
}
Ein einfacher Cache – Constructor Frank Müller
// Put adds the given data with its ID to the cache.
func (c *Cache[D]) Put(id CacheID, data D) {
c.mu.Lock()
defer c.mu.Unlock()
ci := &cacheItem[D]{
eol: time.Now().Add(c.ttl),
data: data,
}
c.cache[id] = ci
}
Ein einfacher Cache – Put Data Frank Müller
// User is a user of the system.
type User struct { ... }
func (u *User) ID() string { ... }
// Create a new user cache.
userCache := NewCache[*User](30 * time.Minute)
// Create a user and put it in the cache.
pooh := NewUser("Pooh", "Bear")
userCache.Put(pooh.ID(), pooh)
Ein einfacher Cache – Nutzung Frank Müller
Einschränkungen
• Jedes zusätzliche Sprachmittel erhöht die Komplexität
• Die Lernkurve der Sprache hat sich mit Generics erhöht
• Go erlaubt kein Operator Overloading, also auch nicht für Type
Constraints
• Der Binärcode kann bei Generics unter Umständen nicht
optimiert werden
• Zu starker Einsatz kann übergroße Binaries erzeugen
Kritik und Einschränkungen Frank Müller
Migration zu Generics
• Bedarf bei Code Duplications ermitteln und prüfen
• Schrittweise mit kleineren, geschlossenen Packages starten
• Allgemeine Hilfsfunktionen und Datenstrukturen überarbeiten
• Code kontinuierlich testen und Performance prüfen
• Monitoring der Anwendung
• Nicht übermäßig einsetzen und eventuell neue Fehler einführen
Schritt für Schritt Frank Müller
Zusammenfassung
• Mit Version 1.18 erhielt Go Generics wie andere Sprachen zuvor
• Sie passen zum geradlinigen Stil der Sprache bis Version 1.17
• Erlaubte Typen können über Type Constraints definiert werden
• Die Notation der Interfaces wurde hierfür behutsam erweitert
• Generischer Code kann helfen, semantische Duplikate zu
vermeiden
• Übereifriger Einsatz sollte jedoch vermieden werden
Zusammenfassung Frank Müller
Vielen Dank und
weiterhin viel Spaß
Bilderquellen
123RF
Pexels
iStockphoto
Eigene Photos

Weitere ähnliche Inhalte

Ähnlich wie JAX 2023 - Generics in Go

FMK2019 Nutzung von Shell-Skripts in FileMaker by Erich Schmidt
FMK2019 Nutzung von Shell-Skripts in FileMaker by Erich SchmidtFMK2019 Nutzung von Shell-Skripts in FileMaker by Erich Schmidt
FMK2019 Nutzung von Shell-Skripts in FileMaker by Erich Schmidt
Verein FM Konferenz
 
FMK 2013 Konstrukte diverser Programmiersprachen in FileMaker nachgebaut, Tho...
FMK 2013 Konstrukte diverser Programmiersprachen in FileMaker nachgebaut, Tho...FMK 2013 Konstrukte diverser Programmiersprachen in FileMaker nachgebaut, Tho...
FMK 2013 Konstrukte diverser Programmiersprachen in FileMaker nachgebaut, Tho...
Verein FM Konferenz
 

Ähnlich wie JAX 2023 - Generics in Go (20)

TypeScript
TypeScriptTypeScript
TypeScript
 
JAX 2023 - Cloud Provider APIs
JAX 2023 - Cloud Provider APIsJAX 2023 - Cloud Provider APIs
JAX 2023 - Cloud Provider APIs
 
FMK2022 Neue Programmiertechniken von Adam Augusting
FMK2022 Neue Programmiertechniken von Adam AugustingFMK2022 Neue Programmiertechniken von Adam Augusting
FMK2022 Neue Programmiertechniken von Adam Augusting
 
FMK2019 Nutzung von Shell-Skripts in FileMaker by Erich Schmidt
FMK2019 Nutzung von Shell-Skripts in FileMaker by Erich SchmidtFMK2019 Nutzung von Shell-Skripts in FileMaker by Erich Schmidt
FMK2019 Nutzung von Shell-Skripts in FileMaker by Erich Schmidt
 
PLUX.NET – SOFTWAREKOMPOSITION DURCH PLUG & PLAY
PLUX.NET – SOFTWAREKOMPOSITION DURCH PLUG & PLAYPLUX.NET – SOFTWAREKOMPOSITION DURCH PLUG & PLAY
PLUX.NET – SOFTWAREKOMPOSITION DURCH PLUG & PLAY
 
C Sharp Einfuehrung Teil 2
C Sharp Einfuehrung Teil 2C Sharp Einfuehrung Teil 2
C Sharp Einfuehrung Teil 2
 
OSMC 2010 | Logverarbeitung mit syslog-ng - Status und Zukunft by Martin Grauel
OSMC 2010 | Logverarbeitung mit syslog-ng - Status und Zukunft by Martin GrauelOSMC 2010 | Logverarbeitung mit syslog-ng - Status und Zukunft by Martin Grauel
OSMC 2010 | Logverarbeitung mit syslog-ng - Status und Zukunft by Martin Grauel
 
FLOW3-Workshop F3X12
FLOW3-Workshop F3X12FLOW3-Workshop F3X12
FLOW3-Workshop F3X12
 
Neuerungen in TypoScript in TYPO3 Version 4.7
Neuerungen in TypoScript in TYPO3 Version 4.7Neuerungen in TypoScript in TYPO3 Version 4.7
Neuerungen in TypoScript in TYPO3 Version 4.7
 
System-Management-Trio: Zentrale Verwaltung mit facter, puppet und augeas
System-Management-Trio: Zentrale Verwaltung mit facter, puppet und augeasSystem-Management-Trio: Zentrale Verwaltung mit facter, puppet und augeas
System-Management-Trio: Zentrale Verwaltung mit facter, puppet und augeas
 
Devs@Home - Einführung in Go
Devs@Home - Einführung in GoDevs@Home - Einführung in Go
Devs@Home - Einführung in Go
 
Typ-sichere DSLs
Typ-sichere DSLsTyp-sichere DSLs
Typ-sichere DSLs
 
FMK 2013 Konstrukte diverser Programmiersprachen in FileMaker nachgebaut, Tho...
FMK 2013 Konstrukte diverser Programmiersprachen in FileMaker nachgebaut, Tho...FMK 2013 Konstrukte diverser Programmiersprachen in FileMaker nachgebaut, Tho...
FMK 2013 Konstrukte diverser Programmiersprachen in FileMaker nachgebaut, Tho...
 
System-Management-Trio: Zentrale Verwaltung mit facter, puppet und augeas
System-Management-Trio: Zentrale Verwaltung mit facter, puppet und augeasSystem-Management-Trio: Zentrale Verwaltung mit facter, puppet und augeas
System-Management-Trio: Zentrale Verwaltung mit facter, puppet und augeas
 
Vielfalt vs. Abstraktion - Der Jakobsweg der modellbasierten GUI-Entwicklung
Vielfalt vs. Abstraktion - Der Jakobsweg der modellbasierten GUI-EntwicklungVielfalt vs. Abstraktion - Der Jakobsweg der modellbasierten GUI-Entwicklung
Vielfalt vs. Abstraktion - Der Jakobsweg der modellbasierten GUI-Entwicklung
 
Warum ECMAScript 6 die Welt ein Stückchen besser macht
Warum ECMAScript 6 die Welt ein Stückchen besser machtWarum ECMAScript 6 die Welt ein Stückchen besser macht
Warum ECMAScript 6 die Welt ein Stückchen besser macht
 
FM2014: Einführung in Function Scripting by Thomas Hirt
FM2014: Einführung in Function Scripting by Thomas HirtFM2014: Einführung in Function Scripting by Thomas Hirt
FM2014: Einführung in Function Scripting by Thomas Hirt
 
Drupal und twig
Drupal und twigDrupal und twig
Drupal und twig
 
TYPO3 CMS 7.3 - Die Neuerungen - pluswerk
TYPO3 CMS 7.3 - Die Neuerungen - pluswerkTYPO3 CMS 7.3 - Die Neuerungen - pluswerk
TYPO3 CMS 7.3 - Die Neuerungen - pluswerk
 
Große Applikationen mit AngularJS
Große Applikationen mit AngularJSGroße Applikationen mit AngularJS
Große Applikationen mit AngularJS
 

Mehr von Frank Müller

RESTful Web Applications with Google Go
RESTful Web Applications with Google GoRESTful Web Applications with Google Go
RESTful Web Applications with Google Go
Frank Müller
 
Pecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches ParadigmaPecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches Paradigma
Frank Müller
 

Mehr von Frank Müller (20)

Let The Computer Do It
Let The Computer Do ItLet The Computer Do It
Let The Computer Do It
 
Concurrency with Go
Concurrency with GoConcurrency with Go
Concurrency with Go
 
2021 OOP - Kubernetes Operatoren
2021   OOP - Kubernetes Operatoren2021   OOP - Kubernetes Operatoren
2021 OOP - Kubernetes Operatoren
 
Fun with functions
Fun with functionsFun with functions
Fun with functions
 
Blockchains - Mehr als nur digitale Währungen
Blockchains - Mehr als nur digitale WährungenBlockchains - Mehr als nur digitale Währungen
Blockchains - Mehr als nur digitale Währungen
 
Spaß an der Nebenläufigkeit
Spaß an der NebenläufigkeitSpaß an der Nebenläufigkeit
Spaß an der Nebenläufigkeit
 
Go - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare SystemeGo - Googles Sprache für skalierbare Systeme
Go - Googles Sprache für skalierbare Systeme
 
Cloud Provisioning mit Juju
Cloud Provisioning mit JujuCloud Provisioning mit Juju
Cloud Provisioning mit Juju
 
Juju - Scalable Software with Google Go
Juju - Scalable Software with Google GoJuju - Scalable Software with Google Go
Juju - Scalable Software with Google Go
 
RESTful Web Applications with Google Go
RESTful Web Applications with Google GoRESTful Web Applications with Google Go
RESTful Web Applications with Google Go
 
Clouds, leicht beherrschbar
Clouds, leicht beherrschbarClouds, leicht beherrschbar
Clouds, leicht beherrschbar
 
Skalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google GoSkalierbare Anwendungen mit Google Go
Skalierbare Anwendungen mit Google Go
 
WTC 2013 - Juju - Mit etwas Magie zur perfekten Cloud
WTC 2013 - Juju - Mit etwas Magie zur perfekten CloudWTC 2013 - Juju - Mit etwas Magie zur perfekten Cloud
WTC 2013 - Juju - Mit etwas Magie zur perfekten Cloud
 
Juju - Google Go in a scalable Environment
Juju - Google Go in a scalable EnvironmentJuju - Google Go in a scalable Environment
Juju - Google Go in a scalable Environment
 
OOP 2013 - Weltweite Entwicklung von Open Source Software
OOP 2013 - Weltweite Entwicklung von Open Source SoftwareOOP 2013 - Weltweite Entwicklung von Open Source Software
OOP 2013 - Weltweite Entwicklung von Open Source Software
 
Beauty and Power of Go
Beauty and Power of GoBeauty and Power of Go
Beauty and Power of Go
 
Pecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches ParadigmaPecha Kucha: Nebenläufigkeit als natürliches Paradigma
Pecha Kucha: Nebenläufigkeit als natürliches Paradigma
 
On Event-Driven Architecture
On Event-Driven ArchitectureOn Event-Driven Architecture
On Event-Driven Architecture
 
Google Go - Good artists borrow, great artists steal.
Google Go - Good artists borrow, great artists steal.Google Go - Good artists borrow, great artists steal.
Google Go - Good artists borrow, great artists steal.
 
Agility And The Way To SOA
Agility And The Way To SOAAgility And The Way To SOA
Agility And The Way To SOA
 

JAX 2023 - Generics in Go

  • 2. •Frank Müller •Oldenburg •1965 geboren •T-Systems International •Enterprise Architect •@themue Vorstellung Frank Müller
  • 4. • Generics sind ein Feature, welches die Nutzung von Typenvariablen ermöglicht • Sie erleichtern die Wiederverwendung von Quelltext • Die Typsicherheit in statischen Sprachen wird dennoch ermöglicht • Je nach Sprache werden generische Funktionen, Strukturen und Interfaces ermöglicht • Die Lesbarkeit wird durch weniger Overhead im Code erhöht Generics in Programmiersprachen Frank Müller
  • 6. • Entwicklung bei Google seit Ende 2007, erstes Release November 2009 • Initial durch Robert Griesemer, Rob Pike und Ken Thompson • Heute große Community • Fokus liegt auf Geschwindigkeit, Nebenläufigkeit und Spaß • Bis heute ist Go abwärtskompatibel • Einsatz rund um Cloud-Native und Microservices Die Programmiersprache Go Frank Müller
  • 7. ❞ Go hat das Ziel, die Sicherheit und Geschwindigkeit einer statisch typisierten kompilierten Sprache mit der Ausdrucksstärke und dem Komfort einer dynamisch typisierten interpretierten Sprache zu verbinden. Zudem soll die Sprache für moderne, stark skalierende Systeme geeignet sein. –Rob Pike
  • 8. • Syntax passt auf eine HTML-Seite • Klare und wenig mehrdeutige Struktur der Sprache • Type Inference und Garbage Collection erlauben ein Arbeiten ähnlich wie in vielen dynamisch typisierten Sprachen • Nebenläufigkeit unterstützt elastische Server-Anwendungen • Compiling ist sehr schnell, Single Binary und Cross Compiling erleichtern die Arbeit in heterogenen Umgebungen Was Spaß macht Frank Müller
  • 9. Go vor den Generics
  • 10. • Doppelter Code für unterschiedliche Typen ‣ Z.B. StringSlice, IntSlice und Float64Slice im Package sort • Aufgabe der Typsicherheit ‣ Einsatz des Empty Interface interface{} Go vor den Generics Frank Müller
  • 11. • Type Assertions auf Empty Interfaces ‣ Risiko von Laufzeitfehlern • Reflection auf Empty Interfaces ‣ Niedrigere Geschwindigkeit und Risiko von Laufzeitfehlern • Code-Generierung mit Tools wie go generate ‣ Erhöhte Build-Zeit und Code-Komplexität Workarounds Frank Müller
  • 13. • Einführung mit Version 1.18 • Einsetzbar bei Funktionen, Structs und Interfaces • Type Constraints erlauben Eingrenzung der erlaubten Typen • So sind einfache, abgeleitete und komplexe Typen als Type Constraints möglich • Vorsichtige Erweiterungen der Syntax Go mit Generics Frank Müller
  • 14. •Ein oder mehrere Typen- Parameter •Typen-Parameter sind any, comparable, Type Sets oder Type Constraints •Spezifikation bei der Nutzung explizit oder implizit Funktionen mit Generics – Allgemein Frank Müller
  • 15. // Type constraint for numbers, constraints is "golang.org/exp/constraints". type Number interface { constraints.Integer | constraints.Float | constraints.Complex } // Add adds any two numbers of the same type. func Add[N Number](i, j N) N { return i+j } // Usage. explicit := Add[byte](47, 11) implicit := Add(47.11, 8.15) Funktionen mit Generics – Beispiel Frank Müller
  • 16. •Ein oder mehrere Typen- Parameter •Typen-Parameter sind bei Nutzung zu spezifizieren •Methoden müssen in der Typenangabe die Anzahl der Typen-Parameter wiederholen Structs mit Generics – Allgemein Frank Müller
  • 17. // Stack defines a simple generic stack data structure. type Stack[T any] struct { data []T } func (s *Stack[T]) Push(item T) int { s.data = append(s.data, item) return len(s.data) } // Usage. s := &Stack[string]{} // Create empty string stack. l := s.Push("Hello, JAX") // Returns 1 Structs mit Generics – Beispiel Frank Müller
  • 18. •Ein oder mehrere Typen- Parameter •Implementierender Typ benötigt die gleiche Typen- Parameter •Methoden in der Implementierung analog zu struct Interfaces mit Generics – Allgemein Frank Müller
  • 19. // KeyValueStore defines the interface to store keys with their values. type KeyValueStore[K comparable, V any] interface { Set(key K, value V) error Get(key K) (V, error) Delete(key K) (V, error) } // Map implements KeyValueStore in-memory using a map. type Map[K comparable, V any] struct { store map[K]V } func (m *Map[K, V]) Set(key K, value V) error { ... } ... Interfaces mit Generics – Definition Frank Müller
  • 20. // StoreDatas identifies and stores a number of data in any key/value store for // string and *Data. The key is retrieved from the data with a helper. func StoreDatas(kvs KeyValueStore[string, *Data], datas ...*Data) error { for _, data := range datas { if err := kvs.Put(GetKey(data), data); err != nil { return err } } return nil } // store uses the in-memory map to store its data. store := NewMap[string, *Data]() // Store takes lots of data to put it into the store. err := StoreDatas(store, lotsOfData...) Interfaces mit Generics – Nutzung Frank Müller
  • 22. • Eingrenzung erlaubter Typen für Typen-Parameter • Alternative in Type Sets werden über die Pipe (|) abgebildet • Für abgeleitete Typen wird die Tilde (~) vorangestellt • Type Constraints können kombiniert werden • Im Package golang.org/exp/constraints sind bereits einige Type Constraints definiert Type Constraints Frank Müller
  • 23. // Signed permits any signed integer types. type Signed interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 } // Unsigned permits any unsigned integer types. type Unsigned interface { ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr } // Integer permits any integer types. It just combines signed and unsigned // integers. type Integer interface { Signed | Unsigned } Einfache Type Constraints Frank Müller
  • 24. // Stringer is now a simple type constraint. type Stringer interface { String() string } // Scaler permits types which can scale scalable, which are type constraints too. type Scaler[S Scalable] interface { Scale(S) S } // NumberStringer permits any own number type able to return itself as string. type NumberStringer interface { Number Stringer } Type Constraints mit Methoden Frank Müller
  • 25. // Different roles in a system. type Administrator struct { ... } func (a *Administrator) ID() string type User struct { ... } ... type Guest struct { ... } ... // Role permits one of the roles and allows to call its ID method. type Role interface { Administrator | User | Guest ID() string } Semantische Type Constraints Frank Müller
  • 27. • Typsichere Datenstrukturen wie Listen, Queues, Stacks, Sets oder Trees, aber auch Caches • Allgemeine Algorithmen wie Sort, Filter, Map oder Reduce auf Strukturen wie Slices und Maps • Generelle Hilfsfunktionen wie Swap Einsatzmöglichkeiten von Generics Frank Müller
  • 28. // Age implements NumberStringer. type Age uint func (a Age) String() string { return fmt.Sprintf("%d year(s)", a) } // Add two numbers. func Add[N Number](i, j N) N { return i+j } // main now uses Age and Add. func main() { var i, j Age = 57, 10 k := Add(i, j) fmt.Printf("Age: %v", k) // Output: "Age: 67 year(s)" } Einfaches Zusammenspiel Frank Müller
  • 29. // FilterMap creates a slice from of new values created by fun() where // it also returns true. func FilterMap[I, O any](ivs []I, fun func(I) (O, bool)) []O { var ovs []O for _, iv := range ivs { if ov, ok := fun(iv); ok { ovs = append(ovs, ov) } } return ovs } Arbeit mit Slices Frank Müller
  • 30. // CacheID is a type alias for string making the meaning clearer. type CacheID = string // cacheItem is an internal wrapper for a cached data. type cacheItem[D any] struct { eol time.Time data D } // Cache stores any data with a cache ID until not used for ttl. type Cache[D any] struct { mu sync.Mutex ttl time.Duration cache map[CacheID]*cacheItem[D] } Ein einfacher Cache – Typen Frank Müller
  • 31. // NewCache creates a cache for any D with the given time to live. func NewCache[D any](ttl time.Duration) *Cache[D] { c := &Cache[D]{ ttl: ttl, cache: make(map[string]*cacheItem[D]), } return c } Ein einfacher Cache – Constructor Frank Müller
  • 32. // Put adds the given data with its ID to the cache. func (c *Cache[D]) Put(id CacheID, data D) { c.mu.Lock() defer c.mu.Unlock() ci := &cacheItem[D]{ eol: time.Now().Add(c.ttl), data: data, } c.cache[id] = ci } Ein einfacher Cache – Put Data Frank Müller
  • 33. // User is a user of the system. type User struct { ... } func (u *User) ID() string { ... } // Create a new user cache. userCache := NewCache[*User](30 * time.Minute) // Create a user and put it in the cache. pooh := NewUser("Pooh", "Bear") userCache.Put(pooh.ID(), pooh) Ein einfacher Cache – Nutzung Frank Müller
  • 35. • Jedes zusätzliche Sprachmittel erhöht die Komplexität • Die Lernkurve der Sprache hat sich mit Generics erhöht • Go erlaubt kein Operator Overloading, also auch nicht für Type Constraints • Der Binärcode kann bei Generics unter Umständen nicht optimiert werden • Zu starker Einsatz kann übergroße Binaries erzeugen Kritik und Einschränkungen Frank Müller
  • 37. • Bedarf bei Code Duplications ermitteln und prüfen • Schrittweise mit kleineren, geschlossenen Packages starten • Allgemeine Hilfsfunktionen und Datenstrukturen überarbeiten • Code kontinuierlich testen und Performance prüfen • Monitoring der Anwendung • Nicht übermäßig einsetzen und eventuell neue Fehler einführen Schritt für Schritt Frank Müller
  • 39. • Mit Version 1.18 erhielt Go Generics wie andere Sprachen zuvor • Sie passen zum geradlinigen Stil der Sprache bis Version 1.17 • Erlaubte Typen können über Type Constraints definiert werden • Die Notation der Interfaces wurde hierfür behutsam erweitert • Generischer Code kann helfen, semantische Duplikate zu vermeiden • Übereifriger Einsatz sollte jedoch vermieden werden Zusammenfassung Frank Müller
  • 40. Vielen Dank und weiterhin viel Spaß Bilderquellen 123RF Pexels iStockphoto Eigene Photos