Slices of structs vs. slices of pointers to structs

Just got curious about this myself. Ran some benchmarks:

type MyStruct struct {
    F1, F2, F3, F4, F5, F6, F7 string
    I1, I2, I3, I4, I5, I6, I7 int64
}

func BenchmarkAppendingStructs(b *testing.B) {
    var s []MyStruct

    for i := 0; i < b.N; i++ {
        s = append(s, MyStruct{})
    }
}

func BenchmarkAppendingPointers(b *testing.B) {
    var s []*MyStruct

    for i := 0; i < b.N; i++ {
        s = append(s, &MyStruct{})
    }
}

Results:

BenchmarkAppendingStructs  1000000        3528 ns/op
BenchmarkAppendingPointers 5000000         246 ns/op

Take aways: we're in nanoseconds. Probably negligible for small slices. But for millions of ops, it's the difference between milliseconds and microseconds.

Btw, I tried running the benchmark again with slices which were pre-allocated (with a capacity of 1000000) to eliminate overhead from append() periodically copying the underlying array. Appending structs dropped 1000ns, appending pointers didn't change at all.


Can you provide general guidelines of when to work with structs directly vs. when to work with pointers to structs?

No, it depends too much on all the other factors you've already mentioned.

The only real answer is: benchmark and see. Every case is different and all the theory in the world doesn't make a difference when you've got actual timings to work with.

(That said, my intuition would be to use pointers, and possibly a sync.Pool to aid the garbage collector: http://golang.org/pkg/sync/#Pool)