In Go1.17, the much-heralded generics finally came out, but not quite. There was no mention of generics in the Go1.17 release documentation, but observers noticed that generics-related code was actually incorporated, but not enabled by default. For now, just play with generics and don’t use them in production.

Generics are expected to be released in Go1.18.

1. Enable generics

The functionality of generics has been added to Go.1.17. If you want to use it, you need to add some parameters to enable it.

$ go version                                                                                                                                                                                                                                                                       ~
go version go1.17 darwin/amd64
Copy the code

You can then see the shadow of generics in the compiled arguments. The following -g argument is required to enable generics:

$ go tool compile -h                                                                                                                                                                                                                                                               ~
usage: compile [options] file.go...
  -% int
    	debug non-static initializers
  -+	compiling runtime
  -B	disable bounds checking
  -C	disable printing of columns in error messages
  -D path
    	set relative path for local imports
  -E	debug symbol export
  -G	accept generic code
Copy the code

Look at an example:

package main

import (
    "fmt"
)

type Addable interface {
	type int.int8.int16.int32.int64.uint.uint8.uint16.uint32.uint64.uintptr.float32.float64.complex64.complex128.string
}

func add[T Addable](a, b T) T {
    return a + b
}

func main(a) {
    fmt.Println(add(1.2))

    fmt.Println(add("foo"."bar"))}Copy the code

If you run the above code directly, you will get the following error, which means that Go1.17 does not support generics by default:

$ go run main.go                                                                                                                                                                                                                       
# command-line-arguments
./main.go:8:2: syntax error: unexpected type, expecting method or interface name
./main.go:14:6: missing function body
./main.go:14:9: syntax error: unexpected [, expecting (
Copy the code

The following parameters need to be added:

$Go Run - gcFlags = -g =3 main.go Trigger 3 foobarCopy the code

The first generic program ran successfully.

2. Type parameters and constraints

In Go generics, two new concepts have been added. One is type parameters. The T in the following code is the type parameter used to represent the generics:

func add[T Addable](a, b T) T {
    return a + b
}
Copy the code

It can be said that Type parameters stand for generic in Go.

Take a look at the code below, where the generic type is any and the code above is a custom Addable.

func print[T any](a T) {
     fmt.Printf("%v", a)
}
Copy the code

The add function is constrained to use only the type defined in Addable. If we remove the string from Addable, the code will report the following error:

$ go run -gcflags=-G=3 main.go
# command-line-arguments
./main.go:24:20: string does not satisfy Addable (string not found in int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr, float32, float64, complex64, complex128)
Copy the code

The print function accepts any type of argument.

These are the two most important concepts of generics in Go: type parameters and constraints.

3. Type inference

When generics are used normally, they are called in the following way, as in the add method:

add[int] (1.2)
add[string] ("foo"."bar")
Copy the code

But it is also legal to write code like this:

add(1.2)
add("foo"."bar")
Copy the code

You can omit the generic arguments. This is part of the work that the Go compiler does. The compiler extrapolates from the actual type passed in, rather than specifying the type of the generic every time you write code.

Type inference makes code much cleaner.

4. Summary

Go generics are all about this, and of course generics can write really complicated code, but that’s what they’re really all about. Generally speaking, it is relatively simple, which is also in line with the design concept of Go.

The Go generics are not officially released yet, and they may change when they are, so do not use generics in production.

Examples of this article are from: github.com/mattn/go-ge…

The text/Rayjun