Skip to content

Commit 6ed788f

Browse files
committed
Update generics example to prepare for iteration
1 parent d51709a commit 6ed788f

File tree

4 files changed

+51
-47
lines changed

4 files changed

+51
-47
lines changed

examples/generics/generics.go

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,22 @@ package main
55

66
import "fmt"
77

8-
// As an example of a generic function, `MapKeys` takes
9-
// a map of any type and returns a slice of its keys.
10-
// This function has two type parameters - `K` and `V`;
11-
// `K` has the `comparable` _constraint_, meaning that
12-
// we can compare values of this type with the `==` and
13-
// `!=` operators. This is required for map keys in Go.
14-
// `V` has the `any` constraint, meaning that it's not
15-
// restricted in any way (`any` is an alias for `interface{}`).
16-
func MapKeys[K comparable, V any](m map[K]V) []K {
17-
r := make([]K, 0, len(m))
18-
for k := range m {
19-
r = append(r, k)
8+
// As an example of a generic function, `SlicesIndex` takes
9+
// a slice of any `comparable` type and an element of that
10+
// type and returns the index of the first occurrence of
11+
// v in s, or -1 if not present. The `comparable` constraint
12+
// means that we can compare values of this type with the
13+
// `==` and `!=` operators. For a more thorough explanation
14+
// of this type signature, see [this blog post](https://go.dev/blog/deconstructing-type-parameters).
15+
// Note that this function exists in the standard library
16+
// as [slices.Index](https://pkg.go.dev/slices#Index).
17+
func SlicesIndex[S ~[]E, E comparable](s S, v E) int {
18+
for i := range s {
19+
if v == s[i] {
20+
return i
21+
}
2022
}
21-
return r
23+
return -1
2224
}
2325

2426
// As an example of a generic type, `List` is a
@@ -45,7 +47,10 @@ func (lst *List[T]) Push(v T) {
4547
}
4648
}
4749

48-
func (lst *List[T]) GetAll() []T {
50+
// AllElements returns all the List elements as a slice.
51+
// In the next example we'll see a more idiomatic way
52+
// of iterating over all elements of custom types.
53+
func (lst *List[T]) AllElements() []T {
4954
var elems []T
5055
for e := lst.head; e != nil; e = e.next {
5156
elems = append(elems, e.val)
@@ -54,21 +59,21 @@ func (lst *List[T]) GetAll() []T {
5459
}
5560

5661
func main() {
57-
var m = map[int]string{1: "2", 2: "4", 4: "8"}
62+
var s = []string{"foo", "bar", "zoo"}
5863

5964
// When invoking generic functions, we can often rely
6065
// on _type inference_. Note that we don't have to
61-
// specify the types for `K` and `V` when
62-
// calling `MapKeys` - the compiler infers them
66+
// specify the types for `S` and `E` when
67+
// calling `SlicesIndex` - the compiler infers them
6368
// automatically.
64-
fmt.Println("keys:", MapKeys(m))
69+
fmt.Println("index of zoo:", SlicesIndex(s, "zoo"))
6570

6671
// ... though we could also specify them explicitly.
67-
_ = MapKeys[int, string](m)
72+
_ = SlicesIndex[[]string, string](s, "zoo")
6873

6974
lst := List[int]{}
7075
lst.Push(10)
7176
lst.Push(13)
7277
lst.Push(23)
73-
fmt.Println("list:", lst.GetAll())
78+
fmt.Println("list:", lst.AllElements())
7479
}

examples/generics/generics.hash

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
91465956a90881ec8b4cca3968b9aa1f6d9f1447
2-
uXlb-AyeYmQ
1+
d6b4792fc509f0dcd84f15ed92097f52a73eb877
2+
MNfKskDAZ6d

examples/generics/generics.sh

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
11
$ go run generics.go
2-
keys: [4 1 2]
2+
index of zoo: 2
33
list: [10 13 23]
4-
5-
# Note: The order of iteration over map keys is not
6-
# defined in Go, so different invocations may
7-
# result in different orders.

public/generics

Lines changed: 23 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)