Golang

Let’s find out if Golang is also subject to the same type erasure as Java or retains type information like Microsoft .NET. Please consider the following program:

  1. package main
  2. import (
  3. "fmt"
  4. "runtime"
  5. )
  6. type List[T any] []T
  7. func (a *List[T]) add(val T) {
  8. *a = append(*a, val)
  9. }
  10. func printLen[T any](list List[T]) {
  11. fmt.Println(len(list))
  12. }
  13. func main() {
  14. var ints List[int]
  15. ints.add(1)
  16. ints.add(2)
  17. ints.add(3)
  18. var strs List[string]
  19. strs.add("Hello")
  20. strs.add("world")
  21. printLen(ints)
  22. printLen(strs)
  23. runtime.Breakpoint()
  24. }

Just like the Java and .NET examples, the above program defines two variables using a very hacky, generic List:

  • ints: a list of int values
  • strs: a list of string values

What do ints and strs look like at runtime? Follow the instructions below to find out:

  1. Launch the container:

    1. docker run -it --rm go-generics-the-hard-way
  2. Load the above program into the Golang debugger:

    1. dlv debug ./05-internals/golang/main.go
  3. Continue until the predefined breakpoint is hit:

    1. continue
    1. 3
    2. 2
    3. > main.main() ./05-internals/golang/main.go:48 (PC: 0x495c0d)
    4. 43:
    5. 44: printLen(ints)
    6. 45: printLen(strs)
    7. 46:
    8. 47: runtime.Breakpoint()
    9. => 48: }
  4. Now that they are loaded into memory we can test the type safety of ints and strs. Unfortunately the Golang debugger dlv does not let us invoke the ints.add(int) function, but we can show that ints definitely maintains its type safety at runtime by trying to assign strs to ints:

    1. set ints=strs

    The above command will fail with the following error:

    1. Command failed: can not convert value of type main.List[string] to main.List[int]
  5. Type quit to exit the debugger.

  6. Type exit to stop and remove the container.

In other words, Go does enforce type safety for generic types at runtime. In fact, it is almost as if generic types do not exist at all in compiled Golang binaries. Check out the next section to find out more!


Next: Runtime instantiation