Why no generics in Go?

Viewed 33684

Disclaimer: I've only played with Go for one day now, so there's a good chance I've missed a lot.

Does anybody know why there is no real support for generics/templates/whatsInAName in Go? So there is a generic map, but that's supplied by the compiler, while a Go programmer can't write her own implementation. With all the talk about making Go as orthogonal as possible, why can I USE a generic type but not CREATE a new one?

Especially when it comes to functional programming, there are lambdas, even closures, but with a static type system lacking generics, how do I write, well, generic higher order functions like filter(predicate, list)? OK, Linked lists and the like can be done with interface{} sacrificing type safety.

As a quick search on SO / Google did not reveal any insights, it looks like generics, if at all, will be added to Go as an afterthought. I do trust Thompson to do way better than the Java guys, but why keep generics out? Or are they planned and just not implemented yet?

5 Answers

To add to and update the excellent answers by @Vinzenz and @user7610.

Although it's far from certain, after over a decade of work it looks like a design for parametric polymorphism, what is colloquially but misleadingly called generics, is coming in the next year or two. It was a very hard problem to find a design that works within the existing language and feels as if it belongs, but Ian Taylor invested a phenomenal amount of energy into the problem and it looks like the answer is now in reach. See https://evrone.com/rob-pike-interview.

"Type Parameters - Draft Design" supports the use of type parameters where you can read functions that handle incoming parameters without depending on the type specified in the function declaration. See https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md.

For example, the PrintSlice function receives a slice of integers or strings and prints it. See https://www.jetbrains.com/help/go/how-to-use-type-parameters-for-generic-programming.html.

package main

import "fmt"

func PrintSlice(type T)(s []T) {
    for _, v := range s {

        fmt.Print(v)
    }
}

func main() {
    PrintSlice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
    PrintSlice([]string{"a", "b", "c", "d"})
}

You can test this example here https://go2goplay.golang.org/p/I09qwKNjxoq. This playground works just like the usual Go playground, but it supports generic code. See https://blog.golang.org/generics-next-step.

Parametric polymorphism basically means 'this function or data structure works identically with any type". That's what we also call generics. Eg the length of an array doesn't depend on what's in the array. See https://news.ycombinator.com/item?id=23560798.

The earliest that generics could be added to Go would be the Go 1.17 release, scheduled for August 2021. See https://blog.golang.org/generics-next-step.

Actually, according to this post:

Many people have concluded (incorrectly) that the Go team’s position is “Go will never have generics.” On the contrary, we understand the potential generics have, both to make Go far more flexible and powerful and to make Go far more complicated. If we are to add generics, we want to do it in a way that gets as much flexibility and power with as little added complexity as possible.

Parametric polymorphism (generics) is under consideration for Go 2.

This approach would introduce the concept of a contract, that can be used to express constraints on type parameters:

contract Addable(a T) {
  a + a // Could be += also
}

Such a contract could then be used thusly:

func Sum(type T Addable)(l []T) (total T) {
  for _, e := range l {
    total += e
  }
  return total
}

This is a proposal at this stage.


Your filter(predicate, list) function could be implemented with a type parameter like this:

func Filter(type T)(f func(T) bool, l []T) (result []T) {
  for _, e := range l {
    if f(e) {
      result = append(result, e)
    }
  }
  return result
}

In this case, there is no need to constrain T.

Related