Last year Ian Lance Taylor and Robert Griesemer released a new draft of Go generics (The Next Step for Generics), and the response from Gopher at home and abroad was overwhelming, with everyone interpreting the draft and this article, and feeling that this version of Go generic design is basically close to Go’s generic goals, and in short, much better than the previous one.
Ian also provided an online compilation tool, go2go, to get a taste of Go generic programming.
What if you compile locally?
Actually Go source code is synced to github, so you just need to download the appropriate branch, compile it yourself, and get this go2go tool. This article guides you if you download, compile, and use this tool, and you can also learn how Go generic code is converted to Go1 code and then run.
Of course, as always, the current design and tools are designed for the draft version, and will change when the official version is released.
First download the Go code, the branch is
By following the steps above, you will be able to compile the latest Go tools that support Go generics.
Writing Go generic code
Next let’s write a Go generic application:
In this example, we define a
NumberString interface, which is an extension of the interface, and you can have only numbers or strings implement this interface with the following declaration:
The main purpose is still to constrain the types in the generic. Because we want to use the
+ symbol in the body of functions that use generic arguments, only numbers and strings support this operator, so in order for the function to compile properly, you need to constrain the type arguments. The
Go compiler finds objects that are
NumberString objects when it compiles them, so they can be summed using the
In this case, the
NumberString interface cannot be implemented by other types, for example, the following code will compile with an error:
Also note that the
go2 code files are currently suffixed with
.go2 to distinguish them from the
You can now compile and run the above code:
How is the Go2 code compiled?
Go2 code to
go1 code for running, which means that it provides generic support through compile-time conversions. So the generic design of
Go is relatively simple, and
Go2 also provides backward compatibility.
You can see what magic
go2go does by converting
Go2 code to
Go1 code with the following command.
The converted Go1 code is as follows:
As you can see, for the generic code in the code, because the type parameter needs to be instantiated when instantiating,
go2go specializes the generic code, generating a special type for each type.
So in our example above, the types of
c2 are different, and their types are
instantiate୦ ୦Concat୦string. Use
instantiate as prefix and type as suffix
୦୦୦ as hyphen.
If the type parameters are the same, the same specialised type is used, e.g.
c3 in the following example, both use the same specialised type
The real code logic of go2go is in go/go2go, which provides the logic for code parsing and conversion, and you can savor the implementation by Ian Lance Taylor and Robert Griesemer. I believe there will be an in-depth Gopher analysis article coming soon.
Then the go2go tool entry code is at cmd/go2go.
Mess up a bit
Since the go2go tool translates Go2 code into Go1 code and specializes the generic types, what happens if we declare a type with the same name as the specialized type? For example, the following code:
We declare the
instantiate୦୦Concat୦int type in the code and then compile and run it:
The result is that the compilation fails because the
go2go conversion program also generates a renamed
go2go is still a conceptual tool and will certainly do optimization and type case handling in the future, the related technology is called
Name mangling, which is something the compiler will do.