A generic struct stores a value whose type is supplied when the struct is used.

generic struct A generic struct can keep the same fields and methods while changing the stored value type. The trace uses a concrete integer box and shows the generic shape in a comment.

Generic Box

size
generic_box.go
Replay: real traced execution (multi-file project)
package main

import "fmt"

// Generic shape: Box[T any] struct { Value T }
type IntBox struct {
	Value int
}

func (box IntBox) String() string {
	return fmt.Sprint(box.Value)
}

func main() {
	var size = 3
	box := IntBox{Value: size}
	text := box.String()

	fmt.Println("size=", size)
	fmt.Println("text=", text)
	fmt.Println("double=", box.Value*2)
}
package main

import "fmt"

// Generic shape: Box[T any] struct { Value T }
type IntBox struct {
	Value int
}

func (box IntBox) String() string {
	return fmt.Sprint(box.Value)
}

func main() {
	var size = 1
	box := IntBox{Value: size}
	text := box.String()

	fmt.Println("size=", size)
	fmt.Println("text=", text)
	fmt.Println("double=", box.Value*2)
}
package main

import "fmt"

// Generic shape: Box[T any] struct { Value T }
type IntBox struct {
	Value int
}

func (box IntBox) String() string {
	return fmt.Sprint(box.Value)
}

func main() {
	var size = 5
	box := IntBox{Value: size}
	text := box.String()

	fmt.Println("size=", size)
	fmt.Println("text=", text)
	fmt.Println("double=", box.Value*2)
}
  1. size ← 3, box ← main.IntBox{Value:3}

    14func main() {15  var size→ 3 = 3 //@size=1, 516  box→ main.IntBox{Value:3} := IntBox{Value: size3}17  text := boxmain.IntBox{Value:3}.String()
  2. func (box IntBox) String() string

    10func (box IntBox) String() string {11  return fmt.Sprint(box.Value3)12}
  3. text ← "3"

    16  box := IntBox{Value: size}17  text→ "3" := boxmain.IntBox{Value:3}.String()1819  fmt.Println("size=", size3)20  fmt.Println("text=", text"3")21  fmt.Println("double=", box.Value3*2)22}
    outputsize= 3
    text= 3
    double= 6
  1. size ← 1, box ← main.IntBox{Value:1}

    14func main() {15  var size→ 1 = 116  box→ main.IntBox{Value:1} := IntBox{Value: size1}17  text := boxmain.IntBox{Value:1}.String()
  2. func (box IntBox) String() string

    10func (box IntBox) String() string {11  return fmt.Sprint(box.Value1)12}
  3. text ← "1"

    16  box := IntBox{Value: size}17  text→ "1" := boxmain.IntBox{Value:1}.String()1819  fmt.Println("size=", size1)20  fmt.Println("text=", text"1")21  fmt.Println("double=", box.Value1*2)22}
    outputsize= 1
    text= 1
    double= 2
  1. size ← 5, box ← main.IntBox{Value:5}

    14func main() {15  var size→ 5 = 516  box→ main.IntBox{Value:5} := IntBox{Value: size5}17  text := boxmain.IntBox{Value:5}.String()
  2. func (box IntBox) String() string

    10func (box IntBox) String() string {11  return fmt.Sprint(box.Value5)12}
  3. text ← "5"

    16  box := IntBox{Value: size}17  text→ "5" := boxmain.IntBox{Value:5}.String()1819  fmt.Println("size=", size5)20  fmt.Println("text=", text"5")21  fmt.Println("double=", box.Value5*2)22}
    outputsize= 5
    text= 5
    double= 10