» Quick Introduction to Go » 2. Intermediate » 2.8 Generics

Generics

Generics in Go were officially introduced in Go 1.18, which is a major step forward in the language's capabilities. With generics, you can write functions and data structures that work with any type while still providing type safety.

package main

import "fmt"

// PrintSlice prints the elements of a slice.
func PrintSlice[T any](s []T) {
    for _, v := range s {
        fmt.Println(v)
    }
}

func main() {
    intSlice := []int{1, 2, 3, 4, 5}
    PrintSlice(intSlice)

    stringSlice := []string{"apple", "orange", "banana"}
    PrintSlice(stringSlice)
}

The PrintSlice function is defined with a type parameter T. The T in square brackets [T any] denotes a type parameter, and any is a type constraint indicating that T can be any type.

When calling PrintSlice, the type parameter is inferred based on the type of the argument passed to the function. This allows you to write generic code that works with different types.

You can have multiple type parameters in your declaration.

package main

import "fmt"

// Map is a generic map implementation using the built-in map type.
type Map[K comparable, V any] map[K]V

func (m Map[K, V]) Put(key K, value V) {
	m[key] = value
}

func (m Map[K, V]) Get(key K) (V, bool) {
	value, ok := m[key]
	return value, ok
}

func main() {
	intStringMap := make(Map[int, string])
	intStringMap.Put(1, "one")
	intStringMap.Put(2, "two")
	intStringMap.Put(3, "three")

	value, exists := intStringMap.Get(2)
	if exists {
		fmt.Println("Key 2 found, Value:", value)
	} else {
		fmt.Println("Key 2 not found.")
	}

	stringFloatMap := make(Map[string, float64])
	stringFloatMap.Put("pi", 3.14)
	stringFloatMap.Put("e", 2.718)

	value2, exists := stringFloatMap.Get("pi")
	if exists {
		fmt.Println("Key 'pi' found, Value:", value2)
	} else {
		fmt.Println("Key 'pi' not found.")
	}
}

Code Challenge

Implement a generic stack data structure in Go using generics.

Loading...
> code result goes here
Prev
Next