GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

No menu could be recovered. Follow the blue links in the page.

This view

  • Original page
  • New address

GeezerVison is showing gobyexample.com — Go by Example: Generics

Go by Example: Generics

Starting with version 1.18, Go has added support for generics, also known as type parameters.

package main
import "fmt"

As an example of a generic function, SlicesIndex takes a slice of any comparable type and an element of that type and returns the index of the first occurrence of v in s, or -1 if not present. The comparable constraint means that we can compare values of this type with the == and != operators. For a more thorough explanation of this type signature, see this blog post. Note that this function exists in the standard library as slices.Index.

func SlicesIndex[S ~[]E, E comparable](s S, v E) int {
    for i := range s {
        if v == s[i] {
            return i
        }
    }
    return -1
}

As an example of a generic type, List is a singly-linked list with values of any type.

type List[T any] struct {
    head, tail *element[T]
}
type element[T any] struct {
    next *element[T]
    val  T
}

We can define methods on generic types just like we do on regular types, but we have to keep the type parameters in place. The type is List[T], not List.

func (lst *List[T]) Push(v T) {
    if lst.tail == nil {
        lst.head = &element[T]{val: v}
        lst.tail = lst.head
    } else {
        lst.tail.next = &element[T]{val: v}
        lst.tail = lst.tail.next
    }
}

AllElements returns all the List elements as a slice. In the next example we’ll see a more idiomatic way of iterating over all elements of custom types.

func (lst *List[T]) AllElements() []T {
    var elems []T
    for e := lst.head; e != nil; e = e.next {
        elems = append(elems, e.val)
    }
    return elems
}
func main() {
    var s = []string{"foo", "bar", "zoo"}

When invoking generic functions, we can often rely on type inference. Note that we don’t have to specify the types for S and E when calling SlicesIndex - the compiler infers them automatically.

    fmt.Println("index of zoo:", SlicesIndex(s, "zoo"))

… though we could also specify them explicitly.

    _ = SlicesIndex[[]string, string](s, "zoo")
    lst := List[int]{}
    lst.Push(10)
    lst.Push(13)
    lst.Push(23)
    fmt.Println("list:", lst.AllElements())
}
$ go run generics.go
index of zoo: 2
list: [10 13 23]

Next example: Range over Iterators.

by Mark McGranaghan and Eli Bendersky | source | license

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.