Slice of pointers to struct vs Slice of struct

1,069 views
Skip to first unread message

Somphol Boonjing

unread,
Mar 2, 2016, 12:28:23 AM3/2/16
to golang-nuts
I have a discussion on this topic with my colleagues and is curious to see how the community see it.

In terms of idiomatic or style, between the two usage patterns, if I want to use a variable to hold a slice of structs, are there any prevailing preference for one pattern over another between []*Person and []Person below?

Say, for example, for this simple struct.

type Person struct {
name    string
surname string
address string
age     int
}

If there is no style guide over this, in what scenarios one is preferred over the other.

FYI.

I run a simple benchmark test on slice creation, and it seems that []*Person performs a bit better than []Person.   

I presume this is because of the cost of copying the struct's value into slice's underlying array when a struct is appended to the slice.    

package main                                                                    
                                                                                
import (                                                                        
        "testing"                                                               
)                                                                               
                                                                                
type Person struct {                                                            
        name    string                                                          
        surname string                                                          
        address string                                                          
        age     int                                                             
}                                                                               
                                                                                
func BenchmarkCreatingSliceOfStruct(b *testing.B) {                             
        persons := []Person{}                                                   
        for i := 0; i < b.N; i++ {                                              
                persons = append(persons, Person{name: "ABCDEF", surname: "ABCDEF", address: "123456", age: 2005})
        }                                                                       
}                                                                               
                                                                                
func BenchmarkCreatingSliceOfPointersToStruct(b *testing.B) {                   
        persons := []*Person{}                                                  
        for i := 0; i < b.N; i++ {                                              
                persons = append(persons, &Person{name: "ABCDEF", surname: "ABCDEF", address: "123456", age: 2005})
        }                                                                       
}

And, this is the result.

/home/_/src/slice$ go test -bench=.
testing: warning: no tests to run
PASS
BenchmarkCreatingSliceOfStruct-12                1000000              1405 ns/op
BenchmarkCreatingSliceOfPointersToStruct-12     10000000               252 ns/op
ok      slice   4.258s





Andrew Gerrand

unread,
Mar 2, 2016, 12:38:52 AM3/2/16
to Somphol Boonjing, golang-nuts
It's impossible to say what the best approach is without knowing more about the program at large.

Questions:
- Where do the Person values come from? (Where are they allocated?)
- Do you care about copying Person values?
  - Should each Person value exist only once? Are duplicates okay?
- Do the Person values have methods?
  - Do those methods manipulate the Person values?

For example: If I were fetching many Person values from a database all at once, I would probably load them into a []Person and have those values be the canonical values. When passing the values around, I might pass them by pointer so that they are not copied and that any operations on them are seen by other users of those values.

But, depending on you program, that might be exactly the wrong choice. You might want Person values to always be copied so that they can be manipulated in isolation by various parts of your program. Or the values might be allocated one by one somewhere, and assuming you want to pass them by pointer then []*Person might be a better way to store them collectively.

There's not idiomatic solution. The only good answer you'll get is "It depends."

Andrew
Reply all
Reply to author
Forward
0 new messages