Go Generic Types
A generic type is a named type written for a placeholder type. One definition can hold values of many types.
A generic stack of ints
A stack is a pile where the last value added is the first one taken. Push adds a value and Pop takes the top value.
package main
import "fmt"
type Stack[T any] struct {
items []T
}
func (s *Stack[T]) Push(value T) {
s.items = append(s.items, value)
}
func (s *Stack[T]) Pop() T {
top := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return top
}
func main() {
var stack Stack[int]
stack.Push(10)
stack.Push(20)
stack.Push(30)
fmt.Println(stack.Pop())
fmt.Println(stack.Pop())
}The same stack holds strings
The same Stack definition now holds strings. Pop still takes the last value pushed.
package main
import "fmt"
type Stack[T any] struct {
items []T
}
func (s *Stack[T]) Push(value T) {
s.items = append(s.items, value)
}
func (s *Stack[T]) Pop() T {
top := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return top
}
func main() {
var stack Stack[string]
stack.Push("fig")
stack.Push("plum")
fmt.Println(stack.Pop())
fmt.Println(stack.Pop())
}A pair with two placeholders
Pair takes two placeholders, one for each field. Each pair fills them with its own two types.
package main
import "fmt"
type Pair[A any, B any] struct {
First A
Second B
}
func main() {
person := Pair[string, int]{First: "Hana", Second: 27}
item := Pair[int, string]{First: 7, Second: "fig"}
fmt.Println(person.First, person.Second)
fmt.Println(item.First, item.Second)
}Example
package main
import "fmt"
type Box[T any] struct {
Label string
Value T
}
func main() {
count := Box[int]{Label: "Count", Value: 42}
word := Box[string]{Label: "Word", Value: "plum"}
fmt.Println(count.Label, count.Value)
fmt.Println(word.Label, word.Value)
}Key points
- A generic type puts its type parameters in square brackets after its name.
- A generic type names a placeholder instead of one fixed type.
- Each use fills in one real type for the placeholder.
- Methods sit on the generic type itself and use its placeholder.
- A type can take two placeholders for two kinds of value.
In this example, Box is a generic struct with a Label field and a Value field. The count box fills the placeholder with int and holds 42. The word box fills the placeholder with string and holds plum. The print lines show each label beside its value.
Note
A generic type is not complete until a real type fills its placeholder.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท Go Playground
Exercise
Which line makes a stack that holds strings?