Skip to content
Generic Data Structures/Algorithms in golang.
Go
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
examples
goinline comment typo May 19, 2016
.gitignore Initial commit Jun 27, 2015
README.md Fixed a typo. Jul 9, 2015

README.md

go-inline

Generic Data Structures/Algorithms in golang via code generation (glorified copy&paste).

One might want to use goinline tool to generate specific implementation of generic data structures, such as map, vector, matrix, set. Or to generate specific implementation of generic algorithms, such as sort, binary search.

Goals:

  • Write code once
  • Simple, readable and tested tested go code (e.g. no templates/language extensions)
  • Type safety and speed all the way (e.g. no reflection)
  • No magic, everything is explicit
How-to

Install goinline.

go get github.com/sasha-s/go-inline/goinline/cmd/goinline
Creating a blueprint.

Blueprint is a package that implements a certain generic data type/algorithm.

Let us consider Vector[Number].

package vector

type Number float64

type Vector []Number

func (v Vector) Sum() Number {
    var s Number
    for _, x := range v {
        s += x
    }
    return s
}

func (v Vector) Dot(w Vector) Number {
    var s Number
    for i, x := range v {
        s += x * w[i]
    }
    return s
}
...

Number is a type parameter: we want to be able to use derived versions Vector[float32] or Vector[int].

Note, that Number is a standalone type. This makes it easy to generate the derived versions.

Since we are using + and * the Vector blueprint can be only used with ints and floats.

Have a look at more complete example

Generating derived code.

In case of Vector[Number]:

goinline -package=github.com/sasha-s/go-inline/examples/blueprints/vector --target-package-name=v -target-dir=. -w "Number->int"

This will use a blueprint from package github.com/sasha-s/go-inline/examples/blueprints/vector, looking for the it in $GOPATH, create a generated version in current (.) folder, will rename the package to v and will replace Number with int in the generated code.

Equivalent go:generate directive: //go:generate goinline -package=github.com/sasha-s/go-inline/examples/blueprints/vector --target-package-name=v -target-dir=. -w Number->int

See vector example.

Note, goinline does not check if the blueprint code compiles. Garbage in, garbage out.

Writing tests so they work after inlining types is tricky, so goinline does not generate tests by default.

goinline tool
goinline -h
Usage of goinline:
  -package="": package to use as a blueprint. Something like `github.com/sasha-s/go-inline/examples/blueprints/concurrentmap`
  -target-dir="": where to put the generated code. Will modify the blueprint (according to package) if empty
  -target-package-name="": package name for the generated code. Ignored if empty
  -tests=false: process tests as well
  -w=false: write result to a file instead of stdout

One could get similar results with some scripting around gofmt -r, given that the blueprints are well-structured.

FAQ
  • Why is there no generics in go?
  • How is it different from
  • copy&paste: c&p is painful to maintain, though if the blueprint is well-structured, the copy&paste is easy.
  • gen: gen works with text/template, goinline starts with working, testable go code, so creating the blueprints is easier and cleaner.
  • goast: goast tries to be smart and infer things, goinline is very explicit. Also, goinline code is shorter and simpler.
  • gotemplate: goinline is more explicit, works with multiple files per blueprint. More details.
You can’t perform that action at this time.