You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4.4 KiB
4.4 KiB
title | layout |
---|---|
Go Generics | slides.html |
Go Generics
- Let's talk about Go's Generics.
- What are they?
- How do I ue them?
- When do I use them?
Type Parameters
Starting with version 1.18, Go has added support for generics, also known as type parameters.
- What's a Type Parameter?
Type parameters enable writing functions that work with multiple types.
Example
Consider the following example:
func Index(xs []string, s string) int {
for i, x := range xs {
if x == s {
return i
}
}
return -1
}
Example (cont)
- What if we want to work with
int
(s)? - We'd have to write another function!
func Index2(xs []int, s int) int {
for i, x := range xs {
if x == s {
return i
}
}
return -1
}
- Note the only difference are the types.
- The core logic is the same!
Code Duplication Sucks 😔
Before Go 1.18:
- Lots of duplicate code! 😱
- Custom code generators! 🤔
- Hard to maintain! 😢
Generic Functions 🥳
Let's rewrite our example go use Type Parameters!
func Index[T comparable](s []T, x T) int {
for i, v := range s {
if v == x {
return i
}
}
return -1
}
Instantiation
- We can use this new generic
Index
function:
xs := []int{1, 7, 4, 3}
i := Index[int](xs, 7)
fmt.Println(i) // 1
- Or we can instantiate a function with a type:
fIndex := Index[float64]
- And use this like a normal function.
xs := []float64{1.2, 3.4, 5.6, 3.14}
i := fIndex(xs, 5.6)
fmt.Println(i) // 2
Type Parameter Syntax
Type Parameters look like this:
func Foo[comparable T](xs T, s T) int
That is the type parameters are defined in "square brackets" in the form of:
[constraint T1, constraint T2, ...]
Constraints
- So what are constraints then?
- Let's have a look at comparable
type comparable interface{ comparable }
comparable is an interface that is implemented by all comparable types (booleans, numbers, strings, pointers, channels, arrays of comparable types, structs whose fields are all comparable types)...
Constraints (cont)
- So Constraints are interfaces?
- Yes!
For example:
type comparable interface {
Integer|Float|~string
}
Another Example
Let's look at another example:
func Min(x, y float64) float64 {
if x < y {
return x
}
return y
}
Another Example (cont)
We can define this as a generic function:
import "golang.org/x/exp/constraints"
func Min[T constraints.Ordered](x, y T) T {
if x < y {
return x
}
return y
And call it like this:
x := Min(3, 7)
fmt.Println(x) // 3
- This is Go's Type Inference at play!
- The compiler will work out the types for you!
When to use?! 🤔
My advice:
- Write normal code!
- It's okay to duplicate code!
- Rule of three.
- Generics are powerful, simple to use!
- But no need to rewrite everything as generics! 🤣
🎬 The End 🎬
- Type Parameters: functions with multiple types
- Type Constraints: interfaces of the set of types
- Type Inference: just write normal code
package main
import "fmt"
type Integer interface {
int | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64
}
type Float interface {
float32 | float64
}
type Ordered interface {
Integer | Float | ~string
}
func Min[T Ordered](x, y T) T {
if x < y {
return x
}
return y
}
func main() {
fmt.Println(Min(3, 7)) // 3
fmt.Println(Min(1.2, 3.4)) // 1.2
}