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. "reflect"
  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. // Declare a new List[int] normally and add some values to it.
  15. var ints List[int]
  16. ints.add(1)
  17. ints.add(2)
  18. ints.add(3)
  19. // Get the type of the generic List in order to build a new List[string]
  20. // at runtime using reflection.
  21. _ = reflect.TypeOf(List)
  22. // There is no point in going any further as the above statement simply
  23. // does not compile.
  24. //
  25. // Generics in Go do not exist at runtime. Like Java they are a compile-time
  26. // convenience feature. While we already claimed that generic types in Go
  27. // do *not* get type erased, that is not entirely true.
  28. //
  29. // The generic "template", in this case "List[T any]" is erased at runtime.
  30. //
  31. // The only type that exists at runtime is main.List[int], because that is
  32. // what was instantiated.
  33. //
  34. // The Go compiler transforms all instantiated, generic types into concrete
  35. // types and drops the generic "templates" from the compiled binary.
  36. }

The code comments in the above program describe why Go does not support runtime instantiation from generic types. More importantly, the above program illustrates that Go does not maintain any knowledge of the generic “templates” used to instantiate concrete types once the code is compiled.

To run the above program, please follow these instructions:


:warning: Please note

The go build command below uses the flag -tags invalid. This flag instructs Go to include 05-internals/03-runtime-instantiation/golang/main.go in the compilation. Normally this file has a build constraint that prevents it from being considered to prevent:

  • Dev tools (ex. an IDE such as VS Code) from constantly warning this file is in error
  • a failed go test ./... command from the root of this repository

However, the entire point of this example is to demonstrate that failure, so the file needs to be “activated.”


  1. Launch the container:

    1. docker run -it --rm go-generics-the-hard-way
  2. Attempt to build the program:

    1. go build -tags invalid ./05-internals/03-runtime-instantiation/golang/

    and the following compiler error will occur:

    1. # go-generics-the-hard-way/05-internals/03-runtime-instantiation/golang
    2. 05-internals/03-runtime-instantiation/golang/main.go:46:21: cannot use generic type List without instantiation
  3. Type exit to stop and remove the container.

Generics are not useful in Go until instantiated, and at the moment there is no way to refer to generic “templates” using reflection, which means it is not possible to instantiate new types using generics at runtime.

Please continue reading to see how Java, .NET, and Golang held up under this section’s scrutiny…


Next: In summary