Is everything passed as a value in Go?

424 views
Skip to first unread message

st ov

unread,
Apr 18, 2017, 5:13:14 PM4/18/17
to golang-nuts
I read everything is pass-by-value in Go, is that correct? 
What does it encompass? Are there any exceptions?

Does that mean the following:

int passes full integer byte value
float64 passes full float byte value
string passes full string []byte value
slice passes pointer value to slice in memory
map passes pointer value to map in memory
func passes pointer value to func in memory
interface passes pointer value to interface object in memory


Message has been deleted

Dave Cheney

unread,
Apr 18, 2017, 5:19:17 PM4/18/17
to golang-nuts
That is correct, every assignment in Go is a copy, including every function argument and return value.

Jan Mercl

unread,
Apr 18, 2017, 5:21:20 PM4/18/17
to st ov, golang-nuts
On Tue, Apr 18, 2017 at 11:13 PM st ov <so.q...@gmail.com> wrote:

> I read everything is pass-by-value in Go, is that correct?
> What does it encompass? Are there any exceptions?
>
> Does that mean the following:
>
> int passes full integer byte value
> float64 passes full float byte value
> string passes full string []byte value

less, string is a 2 word value (struct)

> slice passes pointer value to slice in memory

more, slice is a 3 word value (struct)

> map passes pointer value to map in memory
> func passes pointer value to func in memory

yes - in the first approximation

> interface passes pointer value to interface object in memory

more, interface is a 2 word value (struct)

--

-j

Ian Lance Taylor

unread,
Apr 18, 2017, 5:21:41 PM4/18/17
to st ov, golang-nuts
On Tue, Apr 18, 2017 at 2:13 PM, st ov <so.q...@gmail.com> wrote:
> I read everything is pass-by-value in Go, is that correct?
> What does it encompass? Are there any exceptions?

There are no exceptions. But it does require a clear understanding of
what Go means by a value.

> Does that mean the following:
>
> int passes full integer byte value
> float64 passes full float byte value
> string passes full string []byte value

Not really, a string passes a pointer (to an immutable []byte) and a length.

> slice passes pointer value to slice in memory

Not really, a slice passes a pointer to a backing array, a length, and
a capacity.

> map passes pointer value to map in memory
> func passes pointer value to func in memory
> interface passes pointer value to interface object in memory

Almost, an interface passes a pointer to a method table and a pointer value.

See https://research.swtch.com/godata .

Ian

st ov

unread,
Apr 18, 2017, 5:30:29 PM4/18/17
to golang-nuts
Wow! Thanks everyone!

So if I got this right, Go always makes a copy but whats actually being copied differs by type.

It seems that I don't need to worry about a lot of data being copied about with the larger data structures, but by passing the pointer value by default isn't that an implicit pass-by-reference?

Caleb Spare

unread,
Apr 18, 2017, 5:34:03 PM4/18/17
to Ian Lance Taylor, st ov, golang-nuts
The fact that https://github.com/golang/go/issues/5083 still hasn't
been sorted out means that it's hard to explain this to people using
officially sanctioned terminology. I usually end up just using the
phrase "reference types" along with some further description of what I
mean (in particular to distinguish from something like C++
references). It would be quite helpful if we could nail this down at
some point. Having a good spec-level description means that we
shouldn't have to talk about machine words or method tables to explain
what values are.

We could even make up a new term if we don't like the baggage of
"reference". (As I joked in a previous thread, "goference".)
> --
> 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.

Konstantin Khomoutov

unread,
Apr 22, 2017, 11:41:22 AM4/22/17
to st ov, golang-nuts
On Tue, 18 Apr 2017 14:30:29 -0700 (PDT)
st ov <so.q...@gmail.com> wrote:

> Wow! Thanks everyone!
>
> So if I got this right, Go always makes a copy but whats actually
> being copied differs by type.
>
> It seems that I don't need to worry about a lot of data being copied
> about with the larger data structures, but by passing the pointer
> value by default isn't that an implicit pass-by-reference?

Yes, and that's what Caleb talked about: the current language spec
appears to only clearly speak about the slices by saying a slice
"...is a descriptor to...".

In Go, the following things have reference semantics: functions,
slices, channels and maps. That is, they can be thought of as being
descriptors to the underlying "stuff". (Well, if you're into C, it's
probably easier to understand function values as being pointers.)

Note two things.

The first one is that it was probably possible to make all those values
have non-reference semantics.

The second is that you can easily create a type which has reference
semantics yourself -- by having a pointer value in some struct value:

type B struct {
PtrA *A
X int
}

b := B{PtrA: &a}
c := b

Note how c.X and b.X are different variables (with different addresses)
while both c and b refer to the same variable via their PtrA fields.

These two things combined actually represent a larger problem to
consider: there are types which have more sensible usage patterns when
made implement reference semantics than otherwise. Say, suppose the
channels would have made implement non-reference semantics. Then
assigning a value containing a channel to a variable would involve
actual copying of the whole channel -- locking it, allocating all the
underlying stuff for the new channel, initializing it, copying any
buffered data over etc. But now what would that really buy anyone?
The whole reason channels exist is that several concurrent goroutines
access *the same* channel value. So should the channels have
non-reference semantics, everyone would have to use pointers to them.
Consider slices. They explicitly were designed to serve as "views"
into underlying arrays, and that's why they can be though of as keeping
references to those arrays. Copying a function value by duplicating
the function's body has almost no sense in a compiled language (if at
all possible to implement given that on popular contemporary H/W
architectures the program's code segment is typically not writable and
data segments are not executable).

Maps it supposedly the only data type with reference semantics which
IMO is sort of in a grey area because non-reference semantics for it
would be sensible, too.

st ov

unread,
Apr 23, 2017, 3:35:34 PM4/23/17
to golang-nuts, so.q...@gmail.com
Thank you for explicitly listing all reference semantics and more importantly the considerations given for their use!

oju...@gmail.com

unread,
Apr 25, 2017, 8:56:36 AM4/25/17
to golang-nuts, so.q...@gmail.com
Go is meant to be fast. The choice for pass by value or by reference for each embedded type was carefully chosen having that in mind.
Pass by value reduces the heap usage because function calls can make a value copy instead of keeping the value at the heap.
Whenever a value is passed by reference the compiler must keep the value in heap, just for the sake of sharing the address.
Reducing the heap usage alleviates the load for the garbage collector resulting in improved overall performance of the generated code.
Reply all
Reply to author
Forward
0 new messages