← Back to Go Course | Chapter 12: Generics | Lesson 4 of 6

Generic Types

A generic type is like a container design (say, a box) that you can build to hold whatever kind of item you decide when you actually make one.

Defining a Generic Struct

A struct type can declare its own type parameter in square brackets right after its name, letting the same struct definition work with any element type chosen when it's instantiated.

Example: Defining a Generic Struct

markup
package main

import "fmt"

type Box[T any] struct {
	Value T
}

func main() {
	intBox := Box[int]{Value: 42}
	strBox := Box[string]{Value: "hello"}
	fmt.Println(intBox.Value, strBox.Value)
}

Methods on Generic Types

Defining a method on a generic type requires repeating its type parameter in the method's receiver clause, after which the parameter behaves like any other type inside that method.

Note: The type parameter name in the receiver (here T) must match how it's used in the method body.

Example: Methods on Generic Types

markup
package main

import "fmt"

type Stack[T any] struct {
	items []T
}

func (s *Stack[T]) Push(v T) {
	s.items = append(s.items, v)
}

func (s *Stack[T]) Pop() (T, bool) {
	var zero T
	if len(s.items) == 0 {
		return zero, false
	}
	last := s.items[len(s.items)-1]
	s.items = s.items[:len(s.items)-1]
	return last, true
}

func main() {
	s := &Stack[int]{}
	s.Push(1)
	s.Push(2)
	v, _ := s.Pop()
	fmt.Println(v)
}

Instantiating a Generic Type

A generic type is used by supplying a concrete type in square brackets, either explicitly (Stack[int]{}) or inferred from a constructor function's arguments.

Example: Instantiating a Generic Type

markup
package main

import "fmt"

type Pair[T any] struct {
	First, Second T
}

func NewPair[T any](a, b T) Pair[T] {
	return Pair[T]{First: a, Second: b}
}

func main() {
	p := NewPair(1, 2)
	fmt.Println(p.First, p.Second)
}
Common Mistakes
  1. Forgetting a generic struct's type parameter must be specified (or inferred) whenever the type is instantiated, e.g. Stack[int]{}.
  2. Defining methods on a generic type without repeating its type parameter in the method's receiver, which is required syntax.
  3. Trying to mix multiple unrelated concrete types in one instantiation of a generic type meant for a single element type.
Chapter Summary
  • A struct (or other type) can declare its own type parameters, making it a generic type.
  • Methods on a generic type must repeat the type parameter in the receiver, e.g. func (s *Stack[T]) Push(v T).
  • A generic type is instantiated by supplying a concrete type, e.g. Stack[int]{} or Stack[string]{}.
  • Generic types are ideal for reusable data structures like stacks, queues, and linked lists.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.