Lab 10: Generics Advanced

Time: 45 minutes | Level: Advanced | Docker: docker run -it --rm golang:1.22-alpine sh

Overview

Master Go generics: interface union constraints, type sets, generic data structures (Stack, Queue, Set, OrderedMap), and functional algorithms (Map, Filter, Reduce, GroupBy).


Step 1: Generic Constraints — Interface Unions

package main

import (
	"fmt"
	"math"
)

// Type set constraint: only these concrete types
type Integer interface {
	int | int8 | int16 | int32 | int64
}

type Float interface {
	float32 | float64
}

// Union constraint
type Number interface {
	Integer | Float
}

// ~T means "T and any type whose underlying type is T"
type Ordered interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 |
		~float32 | ~float64 |
		~string
}

func Sum[T Number](nums []T) T {
	var total T
	for _, n := range nums {
		total += n
	}
	return total
}

func Min[T Ordered](a, b T) T {
	if a < b {
		return a
	}
	return b
}

func Max[T Ordered](a, b T) T {
	if a > b {
		return a
	}
	return b
}

func Abs[T Integer | Float](x T) T {
	if x < 0 {
		return -x
	}
	return x
}

func Distance[T Float](x1, y1, x2, y2 T) T {
	dx := x2 - x1
	dy := y2 - y1
	return T(math.Sqrt(float64(dx*dx + dy*dy)))
}

func main() {
	fmt.Println("Sum[int]:", Sum([]int{1, 2, 3, 4, 5}))
	fmt.Println("Sum[float64]:", Sum([]float64{1.1, 2.2, 3.3}))
	fmt.Println("Min[string]:", Min("apple", "banana"))
	fmt.Println("Max[int]:", Max(3, 7))
	fmt.Println("Abs[int]:", Abs(-42))
	fmt.Printf("Distance: %.4f\n", Distance(0.0, 0.0, 3.0, 4.0))
}

Step 2: Generic Data Structures — Stack & Queue


Step 3: Generic Set


Step 4: Generic Algorithms — Map/Filter/Reduce


Step 5: OrderedMap (Generic)


Step 6: Type Inference


Step 7: Constraints from cmp Package (Go 1.21)


Step 8: Capstone — Full Verified Demo

📸 Verified Output:


Summary

Feature
Syntax
Notes

Basic constraint

[T Number]

Named interface

Union

int | float64 | string

Type set

Tilde

~int

int + named types with int underlying

cmp.Ordered

stdlib Go 1.21

All ordered types

Type inference

Sum([]int{1,2})

Compiler infers T=int

Generic struct

Stack[T any]

Methods on generic types

Comparable

[K comparable]

Can use as map key

Key Takeaways:

  • Generic constraints use interfaces with type sets (Go 1.18+)

  • ~T means "T or any type with underlying type T" — crucial for custom types

  • Type inference eliminates most explicit [T] annotations at call sites

  • cmp.Ordered (Go 1.21) replaces custom Ordered constraints

  • Generics beat interface{} for type safety; prefer them over reflect for collections

Last updated