go language generics system

Related tags

Miscellaneous gotgo


This document describes the third iteration of my attempt at a reasonable implementation of generics for go based on the idea of template packages.

Quick start

You can compile gotgo by typing


and you can run it on an example template file by typing

./gotgo/gotgo pkg/gotgo/slice.got int string

A complete example is in the example/ subdirectory.

cd example

If you want to see what a template package will look like, check out slice.got, which is a simple package exporting handy functions for slices, such as Map, Fold, Filter, Append, Cat (concat).

The got file

A template package is contained in a got file, ending with the .got extension. As you might be able to guess, "got" stands for "go template". If you call gotgo with a --package-name flag, you can generate a go file which is a member of any package you like.

The got file differs from an ordinary go file only in its package line, which will be something like

package slice(type a, type b a)

This defines a package template named "slice", with two type parameters. The first could be any type, which will be called "a", and the second type, called "b" will default to be the same as "a", if no second type parameter is provided. The default type argument is optional, and will itself default to interface{}. The default type should be either an interface type, or a type defined in terms of other template parameters, although I'm not sure whether/how to enforce this. Your got file should be able to compile with the default type!

Within this package, the types "a" and "b" will be in scope, so the slice got file might contain:

func Append(slice []a, datum a) []a {
    // first expand if needed...
    slice = slice[0:len(slice)+1]
    slice[len(slice)-1] = datum
    return slice

We could also have a function that uses both "a" and "b":

func Map(f func(a) b, slice []a) []b {
    out := make([]b, len(slice))
    for i,v := range slice {
        out[i] = f(v)
    return out

Importing a got package

If you want to use the above package, you typically do so by creating an ordinary go file that has a special import statement that specifies the types desired. Currently, this is not automated, as gotgo is in rapid flux.

import intslice "./slice(int)"

func foo(x int, xs []int, ...) {

This import is valid go (since the language spec states that the interpretation of the import string is implementation-dependent), and is accepted by the go compiler, so long as the slice(int) package has been generated and compiled.

The package name of this templated import may be dependent on the gotgo implementation unless you use the --package-name flag when running gotgo.

Getting fancier with interface types

We can get a bit fancier in the package specification by using interfaces.

package list(type a fmt.Stringer)

import fmt "fmt"

type T struct {
    Datum a
    Next *T
func (l T) String() String {
    if l.Next != nil {
        return l.Datum.String() + ", " + l.Next.String()
    } else {
        return l.Datum.String()

This isn't much different from what I've already described, but there is (will be) an additional twist that isn't shown, which is that if you make the default type an interface, then any type parameter passed to the template must satisfy that interface! This is valuable because it means that you can guarantee that you can't break the compile of any client code unless you change the template signature.

If you write a template that requires a numeric type, such as

package maxmin(type a int)

func max(x,y a) a {
    if x > y { return x }
    return y

then you'll need to use a numeric type as your default. The gotgo system will then enforce that this package may only be parametrized with types that are assignment-compatible3 with int (or whatever default type you choose).

How does it work?

There is a simple program called gotgo, which you pass the filepath to a .got file and a list of types. By default, gotgo outputs the go code to stdout, but if you specify -o foo.go, it will create a file named foo.go.

A zeroconf go build system will need to track down and build imported packages, and in order to work with gotgo, will need to know how to build templated packages. An sketch of a helper for such a build system is provided in the gotimports program, which (non-recursively and incorrectly) dumps some make rules that might be helpful in creating your own Makefile.

Problems solved by gotgo

  • In go, there is no way to write a generic data structure, such as a linked list. As the FAQ points out, this isn't such a problem, since go has a pretty nice stable of built-in data structures, but it is a problem, since sooner or later you'll run into a need for more complicated structures (e.g. perhaps a red-black tree), and you don't want to reimplement them for every data type you use.

  • In go, there is no way to write a generic function whose return type depends on its input, or with two arguments of the same (but variable type). This is a much more serious shortcoming than the previous one, as it means you can't even write generic functions for the existing built-in generic data structures. For example, consider the generic version of

    func Append(x int, xs []int) []int

    which will append the given value to the slice, expanding it if needed. This is precisely the sort of function you'd like to write only once (or twice perhaps, to treat "large" data types differently), but currently copy-and-paste is the only way to reuse this code. (And similarly for methods...)

  • Compile time penalty of templates. In C++, using templates means recompiling the template every time you use it. Using gotgo, however, templates are separately compiled, just like any other go package. So a template need be compiled once by gotgo, and then once for each type it is parametrized by, which is the minimal number of recompiles consistent with allowing the compiler to generate optimal code for each type.

  • In the latest gotgo, you can use the --package-name flag to generate a go file in a given package. This makes it possible to use generics with private data types, or in the same package that defines a data type.

You might also like...
File system event notification library on steroids.

notify Filesystem event notification library on steroids. (under active development) Documentation godoc.org/github.com/rjeczalik/notify Installation

Mobile Blogging System

Mobile Blogging System

An unified key management system to make life easier.
An unified key management system to make life easier.

Safebox An unified key management system to make life easier. The main goal of safebox is to make key backup easier with single main key to derive the

Entitas-Go is a fast Entity Component System Framework (ECS) Go 1.17 port of Entitas v1.13.0 for C# and Unity.

Entitas-Go Entitas-GO is a fast Entity Component System Framework (ECS) Go 1.17 port of Entitas v1.13.0 for C# and Unity. Code Generator Install the l

A golang application to mock the billing system

mock-billing-cli A golang application to mock the billing system in super markets Features View all items & items with filter Refill items with admin

a leaderboard system that can run on any Internet enabled device.

hacktoberfest-leaderboard a leaderboard system that can run on any Internet enabled device. How it works The app updates the leaderboard on README.md

Demo project which implements accumulative loyalty system

Gophermart Demo project which implements accumulative loyalty system POST /api/user/register — user registration; POST /api/user/login — user authenti

Steampipe plugin for the Hypothesis annotation system

Steampipe plugin for the Hypothesis annotation system

A reward-based pseudo-currency system built exclusively for IIT Kanpur campus junta.

IITK Coin IITK Coin is a reward-based pseudo-currency system for the IIT Kanpur campus junta. Detailed vision and regulation rules of this currency ar

David Roundy
David Roundy
Aboriginal Generics: the future is here!

Aboriginal Generics: the future is here! Inspired by this gem of an idea (click the image to go to the original comment): Installation go get github.c

Pavel Vasilev 151 Oct 3, 2022
An implementation of standard generics APIs in Go.

generics This package shows an implementation outlook of proposed generics APIs import "changkun.de/x/generics" Related issues: golang/go#45458 golang

Changkun Ou 25 Dec 5, 2022
Go 1.18 Generics based slice package

The missing slice package A Go-generics (Go 1.18) based functional library with no side-effects that adds the following functions to a slice package:

Steven Soroka 35 Jan 8, 2023
Advent of Code 2021 solutions using Go 1.18 Generics

advent-of-code-2021 Here are my solutions for Advent of Code 2021. This year, I chose to write my solutions using Go 1.18 with generics (by building t

Glenn Lewis 5 Dec 18, 2022
Go-generic - A collection of experiments using Go Generics coming out in Go 1.18

Go Generic - experiments with Go 1.18 beta Data structures: iter.Iter[T any] - l

Matthew Hall 2 Aug 15, 2022
Generic-list-go - Go container/list but with generics

generic-list-go Go container/list but with generics. The code is based on contai

Arne Bahlo 7 Dec 7, 2022
Lithia is an experimental functional programming language with an implicit but strong and dynamic type system.

Lithia is an experimental functional programming language with an implicit but strong and dynamic type system. Lithia is designed around a few core concepts in mind all language features contribute to.

Valentin Knabel 9 Dec 24, 2022
:chart_with_upwards_trend: Monitors Go MemStats + System stats such as Memory, Swap and CPU and sends via UDP anywhere you want for logging etc...

Package stats Package stats allows for gathering of statistics regarding your Go application and system it is running on and sent them via UDP to a se

Go Playgound 163 Nov 10, 2022
Real-time Charging System for Telecom & ISP environments

Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments Features Real-time Online/Offline Charging System (OCS). Account Balance

null 368 Dec 31, 2022
Cross-platform file system notifications for Go.

File system notifications for Go fsnotify utilizes golang.org/x/sys rather than syscall from the standard library. Ensure you have the latest version

fsnotify 7.7k Dec 30, 2022