Re: [go-nuts] my misunderstanding with slice/array re-assignment

572 views
Skip to first unread message

Evan Shaw

unread,
Jun 22, 2012, 8:39:14 PM6/22/12
to Jim Smart, golan...@googlegroups.com
Your problem is that your RemoveAllBars method has a value receiver,
not a pointer receiver. A method that has a value receiver makes a
copy of the receiver when it's called. So when you write:

foo.RemoveAllBars()

a copy of foo is made and then RemoveAllBars runs on that copy,
leaving the original foo untouched. Instead of saying:

func (i Foo) RemoveAllBars()

try

func (i *Foo) RemoveAllBars()

- Evan

Jim Smart

unread,
Jun 22, 2012, 8:45:51 PM6/22/12
to golan...@googlegroups.com, Jim Smart
Evan, many thanks for your prompt and helpful reply!

Hmm sneaky! Good catch.

So would it be best practise to always use pointer receivers in preference to value receivers then?

Cheers,
/J

Jesse McNelis

unread,
Jun 22, 2012, 8:45:55 PM6/22/12
to Jim Smart, golan...@googlegroups.com
On Sat, Jun 23, 2012 at 10:28 AM, Jim Smart <j...@jimsmart.org> wrote:
> Also, can someone also please tell me what the recommended method for
> emptying / resetting an array to zero length is? I am currently attempting
> to do this using i.bars = make([]Bar, 0) -- but I am now wondering if that
> is correct?

Slices have an length and a capacity.
If you want to length to be zero but want to increase the length again
later you probably want to keep the same capacity so you can avoid
making additional allocations.

i.bars = i.bars[:0]
ie. a slice from the beginning of the slice up to but not including
the 0th element will give you a zero length slice that still has it's
original capacity.
If you want to reset the capacity too because it might have been very
large and you want to free that memory, then you just make a new
slice.
If you want the slice to have zero length and zero capacity then you
can just set it to nil.
eg.
i.bar = nil

or you can specify a length and/or a capacity.
eg.
i.bars = make([]Bar,0,100) //zero length, 100 capacity.

- jessta
--
=====================
http://jessta.id.au

Jesse McNelis

unread,
Jun 22, 2012, 8:49:34 PM6/22/12
to Jim Smart, golan...@googlegroups.com
On Sat, Jun 23, 2012 at 10:45 AM, Jim Smart <j...@jimsmart.org> wrote:
> So would it be best practise to always use pointer receivers in preference
> to value receivers then?

Should it be best practise to always use pointer parameters in
preference to value parameters to functions?
Receivers aren't really special, they are just sugar.

--
=====================
http://jessta.id.au

Jim Smart

unread,
Jun 22, 2012, 9:01:25 PM6/22/12
to golan...@googlegroups.com, Jim Smart


On Saturday, June 23, 2012 1:45:55 AM UTC+1, Jesse McNelis wrote:
On Sat, Jun 23, 2012 at 10:28 AM, Jim Smart wrote:
> Also, can someone also please tell me what the recommended method for
> emptying / resetting an array to zero length is? I am currently attempting
> to do this using i.bars = make([]Bar, 0) -- but I am now wondering if that
> is correct?

Slices have an length and a capacity.
If you want to length to be zero but want to increase the length again
later you probably want to keep the same capacity so you can avoid
making additional allocations.

i.bars = i.bars[:0]
ie. a slice from the beginning of the slice up to but not including
the 0th element will give you a zero length slice that still has it's
original capacity.

Thanks that one's really helpful to me!

Can I suggest that this is added to a wiki page (SliceTricks?) and/or somewhere in the Go docs? - it seems really obvious to me now that it's pointed out, but I spent a lot of time trying to find out how to reset a slice's length in such a manner, and it may save someone else some time in future :)

 
If you want to reset the capacity too because it might have been very
large and you want to free that memory, then you just make a new
slice.
If you want the slice to have zero length and zero capacity then you
can just set it to nil.
eg.
i.bar = nil


Ah thanks - also very useful.
 
or you can specify a length and/or a capacity.
eg.
i.bars = make([]Bar,0,100) //zero length, 100 capacity.


...and that was the only one I'd already worked out. Thankfully, pretty much everything else I've played with in Go seems pretty intuitive! :) [famous last words]

Thanks very much for your help, I've learnt a lot today. Appreciated.

Regards,
/J

Jim Smart

unread,
Jun 22, 2012, 9:07:44 PM6/22/12
to golan...@googlegroups.com, Jim Smart


On Saturday, June 23, 2012 1:49:34 AM UTC+1, Jesse McNelis wrote:
On Sat, Jun 23, 2012 at 10:45 AM, Jim Smart <j...@jimsmart.org> wrote:
> So would it be best practise to always use pointer receivers in preference
> to value receivers then?

Should it be best practise to always use pointer parameters in
preference to value parameters to functions?

To answer this and my own question: no, it depends on what you want to do (of course)
 
Receivers aren't really special, they are just sugar.


Understood. Definitely a new kind of sugar to me :) and I'd obviously not given them enough thought.

Very helpful, cheers.
/J

peterGo

unread,
Jun 22, 2012, 11:15:44 PM6/22/12
to golang-nuts
Jim,

> So would it be best practise to always use pointer receivers in preference
> to value receivers then?

Methods, Pointers vs. Values, Go FAQ.
http://golang.org/doc/effective_go.html#pointers_vs_values

Peter

Jim Smart

unread,
Jun 22, 2012, 11:22:31 PM6/22/12
to golan...@googlegroups.com


On Saturday, June 23, 2012 4:15:44 AM UTC+1, peterGo wrote:
Methods, Pointers vs. Values, Go FAQ.
http://golang.org/doc/effective_go.html#pointers_vs_values


Cheers - I had read that, but I had failed to fully take in the fact that pointers vs values also applies to receivers (which are new to me).

But the penny has dropped now, and having a re-read of that now makes much more sense :)

/J
Reply all
Reply to author
Forward
0 new messages