Skip to content

ichiban/soa

Repository files navigation

soa - Structure of Arrays for Go

Go Reference

soa is an SoA code generator and generic SoA slice library.

Code Generator

Installation

To install the code generator, add it as a tool dependency:

go get -tool github.com/ichiban/soa/cmd/soagen

Basic Usage

The basic usage is to include the line //go:generate go tool soagen in your file with the structs you want to generate SoA slices.

Let's say you have point.go containing Point, you can generate point_soa.go containing PointSlice by executing go generate ./....

point.go:

package main

//go:generate go tool soagen

type Point struct {
	X int
	Y int
}

point_soa.go:

// Code generated by soagen; DO NOT EDIT.
package main

type PointSlice struct {
	X []int
	Y []int
}

// And some methods.

Now, PointSlice works as an alternative to []Point.

package main

import "fmt"

func main() {
	// s := make([]Point, 3, 10)
	var s PointSlice
	s = s.Grow(10)
	s = s.Slice(0, 3, s.Cap())

	// s[i] = ...
	s.Set(0, Point{X: 1, Y: 1})
	s.Set(1, Point{X: 2, Y: 2})
	s.Set(2, Point{X: 3, Y: 3})

	for i := 0; i < s.Len(); i++ {
		// p := s[i]
		p := s.Get(i)

		fmt.Printf("s[%d] = (%d, %d)\n", i, p.X, p.Y)
	}
}

Output:

s[0] = (1, 1)
s[1] = (2, 2)
s[2] = (3, 3)

Advanced Usage

Specify the SoA slice name pattern

You can specify the pattern for the SoA slices with `-name`. It'll replace `{{.}}` with the original struct name.

point.go:

package main

//go:generate go tool soagen -name "{{.}}Collection"

type Point struct {
	X int
	Y int
}

point_soa.go

// Code generated by soagen; DO NOT EDIT.
package main

type PointCollection struct {
	X []int
	Y []int
}

// And some methods.

Specify the output filename

You can specify the output filenames with `-out`.

point.go:

package main

//go:generate go tool soagen -out point_gen.go

type Point struct {
	X int
	Y int
}

point_gen.go:

// Code generated by soagen; DO NOT EDIT.
package main

type PointSlice struct {
	X []int
	Y []int
}

// And some methods.

Specify which structs to be processed

If you list struct names, it'll process listed structs only.

foo_bar_baz.go:

package main

//go:generate go tool soagen Foo Baz

type Foo struct {
	X int
	Y int
}

type Bar struct {
	X int
	Y int
}

type Baz struct {
	X int
	Y int
}

foo_bar_baz_soa.go:

// Code generated by soagen; DO NOT EDIT.
package main

type FooSlice struct {
	X []int
	Y []int
}

// And some methods.

type BazSlice struct {
	X []int
	Y []int
}

// And some methods.

Library

You can manipulate SoA slices with the library github.com/ichiban/soa.

It implements slices-compatible functions.

With the library, the example in Basic Usage can be written with much ease.

package main

import (
	"fmt"

	"github.com/ichiban/soa"
)

func main() {
	// s := make([]Point, 0, 10)
	s := soa.Make[PointSlice](0, 10)

	// s = append(s, ...)
	s = soa.Append(s, Point{X: 1, Y: 1}, Point{X: 2, Y: 2}, Point{X: 3, Y: 3})

	// for i, p := range s {
	for i, p := range soa.All(s) {
		fmt.Printf("s[%d] = (%d, %d)\n", i, p.X, p.Y)
	}
}

License

Distributed under the MIT license. See LICENSE for more information.

Contributing

  1. Fork it (https://github.com/ichiban/soa/fork)
  2. Create your feature branch (git checkout -b feature/fooBar)
  3. Commit your changes (git commit -am 'Add some fooBar')
  4. Push to the branch (git push origin feature/fooBar)
  5. Create a new Pull Request

Packages

No packages published

Languages