slice of pointer of struct vs slice of struct

2,063 views
Skip to first unread message

Feby Tanzil

unread,
Oct 20, 2017, 1:25:27 AM10/20/17
to golang-nuts
Hi,

I got vague answers in the internet over this.
Which is better & preferable in Go?

type T struct {
 // some attributes
 ...
}

func a() []T {

}

func b() []*T {

}



Thanks

Jan Mercl

unread,
Oct 20, 2017, 1:34:47 AM10/20/17
to Feby Tanzil, golang-nuts
On Fri, Oct 20, 2017 at 7:25 AM Feby Tanzil <febyt...@gmail.com> wrote:

> Which is better & preferable in Go?

Depends on size of T.

--

-j

Feby Tanzil

unread,
Oct 20, 2017, 3:09:49 AM10/20/17
to golang-nuts
so if I have like 50 attributes then pointer is preferable then
How big is big? I took from https://github.com/golang/go/wiki/CodeReviewComments for receiver, is this applicable for this too?

Assume it's equivalent to passing all its elements as arguments to the method. If that feels too large, it's also too large for the receiver.

roger peppe

unread,
Oct 20, 2017, 3:41:15 AM10/20/17
to Feby Tanzil, golang-nuts
Both are plausible. It depends what you're going to do with the slice
and its elements.

Are the methods on T pointer or value methods (if they're pointer
methods, it's probably best to use []*T) ? Are you going to append
lots of elements to the array (pointers might be faster because
there's less to copy)? Are you going to take the address
of elements in the array (problematic if you do this and then append
to the array, because the addresses may change; also keeping an
address of one element will pin the entire array)? Are you doing lots
of computation on values directly inside T ([]T might give you a
performance boost via cache locality)?

I usually give most weight to the first criterion above - store
objects in the form you're most likely to use for passing
them around.

Dave Cheney

unread,
Oct 20, 2017, 3:47:08 AM10/20/17
to golang-nuts
That's a great way to think about it the 'cost' of copying vs passing the address. Thank you.

Ian Davis

unread,
Oct 20, 2017, 4:40:09 AM10/20/17
to golan...@googlegroups.com
How does that affect the size of []T or []*T ?

Ian

Jan Mercl

unread,
Oct 20, 2017, 4:49:55 AM10/20/17
to Ian Davis, golan...@googlegroups.com
On Fri, Oct 20, 2017 at 10:39 AM Ian Davis <m...@iandavis.com> wrote:

> How does that affect the size of []T or []*T ?

No one said it does. What size of T affects is appending/inserting/deleting items to/from the slice. If one passes around a value of type []T, those operations are probably performed on the value.


--

-j

Bakul Shah

unread,
Oct 20, 2017, 5:07:46 AM10/20/17
to Jan Mercl, Ian Davis, golan...@googlegroups.com
On the flip side, []*T will be less cache/TLB/GC friendly than
[]T, unless T is much larger than a ptr. You are also
allocating an extra pointer per element. For small slices it
probably doesn't matter much either way but when slices hold
milions of objects.... Elements of []T are less likely to be
mangled from random places compared to []*T as in the latter
case you may have access through other ptrs. IO and comm will
also be easier with []T. []*T makes sense where there is
genuine need to share. e.g. put an object on multiple lists.
Otherwise it can often just be premature optimization.

Jan Mercl

unread,
Oct 20, 2017, 5:09:44 AM10/20/17
to Bakul Shah, Ian Davis, golan...@googlegroups.com
On Fri, Oct 20, 2017 at 11:07 AM Bakul Shah <ba...@bitblocks.com> wrote:

> On the flip side, []*T will be less cache/TLB/GC friendly than
> []T, unless T is much larger than a ptr. You are also
> allocating an extra pointer per element. For small slices it
> probably doesn't matter much either way but when slices hold
> milions of objects.... Elements of []T are less likely to be
> mangled from random places compared to []*T as in the latter
> case you may have access through other ptrs. IO and comm will
> also be easier with []T. []*T makes sense where there is
> genuine need to share. e.g. put an object on multiple lists.
> Otherwise it can often just be premature optimization.

That's a correct and more detailed version of "it depends on size of T" ;-)

--

-j

Bakul Shah

unread,
Oct 20, 2017, 5:18:35 AM10/20/17
to Jan Mercl, Ian Davis, golan...@googlegroups.com
On Fri, 20 Oct 2017 09:09:15 -0000 Jan Mercl <0xj...@gmail.com> wrote:
Jan Mercl writes:
>
The point is it depends on a lot more than the size of T!

Juliusz Chroboczek

unread,
Oct 20, 2017, 7:41:32 AM10/20/17
to golan...@googlegroups.com
>> What size of T affects is appending/inserting/deleting items to/from
>> the slice. If one passes around a value of type []T, those operations
>> are probably performed on the value.

> On the flip side, []*T will be less cache/TLB/GC friendly than
> []T, unless T is much larger than a ptr.

On the edge side, []T cannot be easily ranged over in a mutable way:
https://play.golang.org/p/6kpQWkLQEW

-- Juliusz

Henrik Johansson

unread,
Oct 20, 2017, 7:51:40 AM10/20/17
to Juliusz Chroboczek, golan...@googlegroups.com

I have started to use non pointer slices much more as of late.
Every time I bother measuring it is always faster and it is better for the GC (usually, caveats apply).

It also, perhaps naively, feels safer... :)

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tamás Gulácsi

unread,
Oct 20, 2017, 7:57:22 AM10/20/17
to golang-nuts
Which is a good thing: you have to alter the slice explicitly: https://play.golang.org/p/KE2Davl06t

When you pass a pointer, you also pass the right to modify the pointee - ownership.

roger peppe

unread,
Oct 20, 2017, 9:12:13 AM10/20/17
to Tamás Gulácsi, golang-nuts
If I need to mutate elements of an array of by-value structs, I'll
usually do this: https://play.golang.org/p/YUFsOkvKQ4

Then for most of the body of the loop, you can use i and t as if you'd
ranged over pointers
to elements of the slice (no need to explicitly assign to the element).


On 20 October 2017 at 12:57, Tamás Gulácsi <tgula...@gmail.com> wrote:
> Which is a good thing: you have to alter the slice explicitly: https://play.golang.org/p/KE2Davl06t
>
> When you pass a pointer, you also pass the right to modify the pointee - ownership.
>

Feby Tanzil

unread,
Oct 21, 2017, 12:14:48 AM10/21/17
to golang-nuts
hmm, suppose I have struct X that have 50 attributes that represent 50 cols in db, struct Y 4 attributes, 4 cols

and I have :

func FindX() *X {}
func FindXs() []*X {}

func FindY() *Y {}
func FindYs() []*Y {}

I don't care about mutable, since this is only a getter func, or should I care? 
since I already queried to db, and the caller is free to do anything to that result
because X is large, then I prefer pointer,
and then for the sake of consistency, 
others (e.g. struct Y) I set them too as pointer, 
regardless other structs may be a small struct
no receiver func yet for those structs
no modifying, mostly just reading the result

Juliusz Chroboczek

unread,
Oct 21, 2017, 7:01:12 AM10/21/17
to golan...@googlegroups.com
> I have started to use non pointer slices much more as of late.
> Every time I bother measuring it is always faster and it is better for the
> GC (usually, caveats apply).

So do I. I was just pointing out a caveat that tripped me a couple times.

> It also, perhaps naively, feels safer... :)

Not if your structs contain a Mutex.

-- Juliusz

Henrik Johansson

unread,
Oct 22, 2017, 6:22:08 AM10/22/17
to Juliusz Chroboczek, golan...@googlegroups.com
No, you are right but then I have made an explicit decision that state is important and mutable so hopefully I would take that into consideration when exposing the data. 

Reply all
Reply to author
Forward
0 new messages