Is string passed to function by value or by reference?

26,708 views
Skip to first unread message

James Chow

unread,
Nov 29, 2011, 11:32:41 PM11/29/11
to golang-nuts
The go spec says: "Strings behave like arrays of bytes but are
immutable: once created, it is impossible to change the contents of a
string".
Does it means string is passed to function by value?

John Asmuth

unread,
Nov 30, 2011, 12:43:36 AM11/30/11
to golan...@googlegroups.com
In go, everything is pass by value.

A string is a struct that has a length and a pointer to a byte array. When you pass a string to another function, it copies the length and the pointer. As a consequence, the new copied string points to the same underlying data.

r2p2

unread,
Nov 30, 2011, 3:22:46 AM11/30/11
to golan...@googlegroups.com
I have the feeling that it is harder in go do know when you work on a copy and when on the original data.

unread,
Nov 30, 2011, 3:36:24 AM11/30/11
to golang-nuts

Snippet from C code at [http://golang.org/src/pkg/runtime/runtime.h]:

struct String
{
byte* str;
int32 len;
};

The length of this structure is 8 bytes (12 bytes on 64-bit CPUs).

To pass a string to a function, the (current) Go compiler generates
assembly code which copies 8 bytes (12 bytes on 64-bit CPUs) to the
stack frame of the called function, without copying the memory to
which 'str' is pointing.

chris dollin

unread,
Nov 30, 2011, 3:46:15 AM11/30/11
to golan...@googlegroups.com
On 30 November 2011 08:22, r2p2 <robert...@gmx.net> wrote:
> I have the feeling that it is harder in go do know when you work on a copy
> and when on the original data.

It's all copies, but some of the values have references in them:
pointers point to other data, slices refer to an underlying array
(copying the slice doesn't copy the array, only the reference to it),
maps refer to the underlying table lookup structures (so all the
copies of a map refer to the same updateable key-value lookup).

Go (like Java and C) is a pass-by-value language. Like both those
languages, sometimes the things you pass are references to other
things.

Chris

--
Chris "allusive" Dollin

r2p2

unread,
Nov 30, 2011, 3:50:19 AM11/30/11
to golan...@googlegroups.com
I spend too much time with copy constructors in c++. If I hear string I am thinking about the fact that it creates a deep copy itself. I just have to forget this.

6355...@qq.com

unread,
Nov 30, 2011, 3:54:27 AM11/30/11
to golang-nuts
It is by value, but the value is only a 2-word structure containing a
pointer to the string and a length.

in c code, type String is:

struct String
{
byte* str;
int32 len;
};


so in go if we have a String s, the following code

ss := s

only copy the 2-word structure of s to ss

6355...@qq.com

unread,
Nov 30, 2011, 3:56:24 AM11/30/11
to golang-nuts
String is immutable in go, so, there has no need for deep copy

r2p2

unread,
Nov 30, 2011, 4:16:56 AM11/30/11
to golan...@googlegroups.com
Oh, correct. So if every string method creates a new string object, you just have to remember that other objects needs to be copied explicitly. Because some methods create new objects and others not. I like the ruby naming convention, where you have to add an ! if the method modifies the object itself. In C++ you can add const to say: "Hey it is harmless to call this method".

chris dollin

unread,
Nov 30, 2011, 4:38:43 AM11/30/11
to golan...@googlegroups.com
On 30 November 2011 09:16, r2p2 <robert...@gmx.net> wrote:
> Oh, correct. So if every string method creates a new string object,

That depends on what you think a "new string object" means.
Some functions/operators create strings with new underlying
byte arrays, eg string + string will do that. But slicing a string
doesn't create a new underlying byte array -- the new string
value refers into the same array as the value that was sliced.

> you just have to remember that other objects needs to be
> copied explicitly.

In a language with pointers, be they explicit (C, Go) or implicit
(Java), given a pointer variable x and a pointer value y and the
desire to "put y in x", you have to /decide/ whether you want x
and y to end up referring to the same thing, or whether x will
end up pointing to a copy of the thing y points to. Usually the
language has operators that make this easier for "the usual
case". In Java, the = operator will copy the pointer, not the
pointed-to value, and if you need to point to a copy of that
value you have to do so explicitly. /Usually/ you don't and you
have to manage the resulting aliasing, but sometimes you
must.

In Go the choice is weighted differently because there are
values -- like structs -- that can be copied and don't need to
use pointers. So a struct {x, y int}, used eg for points on a plane,
can be passed around freely, with no pointers required.
You don't have to remember to copy such a struct explicitly;
assignment and parameter passing will do that for you.

> Because
> some methods create new objects and others not. I like the ruby naming
> convention, where you have to add an ! if the method modifies the object
> itself. In C++ you can add const to say: "Hey it is harmless to call this
> method".

I think the Go convention is to give functions (including methods)
good names and good godoc.

Miguel Pignatelli

unread,
Nov 30, 2011, 4:55:07 AM11/30/11
to chris dollin, golan...@googlegroups.com
On 30/11/11 08:46, chris dollin wrote:
> pointers point to other data, slices refer to an underlying array
> (copying the slice doesn't copy the array, only the reference to it),
> maps refer to the underlying table lookup structures (so all the
> copies of a map refer to the same updateable key-value lookup).

I would add...
interfaces have 2 pointers (to the concrete value assigned to the
variable, and that value’s type descriptor) so passing them by value is
also cheap and functions also store pointers, so they are also cheap to
pass by value.

M;

unread,
Nov 30, 2011, 6:31:38 AM11/30/11
to golang-nuts
On Nov 30, 9:46 am, chris dollin <ehog.he...@googlemail.com> wrote:
> Go (like Java and C) is a pass-by-value language. Like both those
> languages, sometimes the things you pass are references to other
> things.

... I am highly confused by your naming convention ...

Under your naming convention, all programming languages are pass-by-
value. If all of them are pass-by-value, there would be no point to
use this term - it has no power to distinguish.

In my opinion, Java is pass-by-reference (except for low-level types
such as "int").

C has no concept of objects. The compiler has no free will as to the
manner in which data is represented in memory. The concepts "pass-by-
value" or "pass-by-reference" in conjunction with C seem pointless,
since in C you cannot hide anything behind a type - *encapsulation* is
a completely alien concept to C. The programmer is provided with
access to a linear address space, gives type-level interpretations to
data existing in the linear address space, and writes functions
manipulating the data - that's all there is in C.

In my opinion, Go values of type interface{} encapsulating a pointer
to an object are passing the object by reference.

unread,
Nov 30, 2011, 6:33:09 AM11/30/11
to golang-nuts

You can use http://doc.qt.nokia.com/latest/qstring.html

It uses implicit sharing.

unread,
Nov 30, 2011, 6:46:06 AM11/30/11
to golang-nuts
On Nov 30, 10:16 am, r2p2 <robert-pet...@gmx.net> wrote:
> In C++ you can add const to say: "Hey it is harmless to call
> this method".

C/C++ const is only a convention (i.e: it doesn't enforce
immutability). If you call a C++ const method, it may happen that the
method will modify the object.

r2p2

unread,
Nov 30, 2011, 6:53:57 AM11/30/11
to golan...@googlegroups.com
No I think not. If I declare a method as const then the compiler will not allow calling a non-const method on that object (from inside the const method). Well, I work with the gnu compiler collection, I don't know the M$ compiler behavior.

chris dollin

unread,
Nov 30, 2011, 6:57:38 AM11/30/11
to ⚛, golang-nuts
On 30 November 2011 11:31, ⚛ <0xe2.0x...@gmail.com> wrote:
> On Nov 30, 9:46 am, chris dollin <ehog.he...@googlemail.com> wrote:
>> Go (like Java and C) is a pass-by-value language. Like both those
>> languages, sometimes the things you pass are references to other
>> things.
>
> ... I am highly confused by your naming convention ...

For pass-by-value (aka call-by-value)? As far as I'm aware, it's
pretty much the traditional one.

> Under your naming convention, all programming languages are pass-by-
> value.

Not true. Both Pascal and C++ can do pass-by-reference
(Pascal with VAR parameters, C++ with references).
Algol 60 has pass-by-"name". Algol68 can be viewed that
way.

> If all of them are pass-by-value, there would be no point to
> use this term - it has no power to distinguish.

Indeed.

> In my opinion, Java is pass-by-reference (except for low-level types
> such as "int").

No, Java is a pass-by-value language. HOWEVER, the non-primitive
values are all references to "objects", and getting at fields of
objects does an implicit dereference.

You might say that this is just wordgames, but there's a real
behavioural difference. In a pass-by-reference language,
(strictly, in a pass-by-reference context in such a language),
the callee can change the value of a variable in the caller.

class Example {

public static void main( String [] args ) {
String pickle = "Branston";
callee( pickle );
System.err.println( pickle );
}

void callee( String argument ) {
argument = "HomeMade";
}
}

main's pickle is not updated by calling callee. Similar code
in Pascal with a VAR parameter, or C++ with a &wossname
parameter, would update the pickle.

> C has no concept of objects.

Not OO-like objects with methods and such, no.

> The compiler has no free will as to the
> manner in which data is represented in memory.

It may pad as it sees fit between struct elements; it may lay
the automatic variables of a function out in the stack as it
finds convenient; it may order the static-extent variables
of a compilation unit or program to satisfy its whims.

> The concepts "pass-by-
> value" or "pass-by-reference" in conjunction with C seem pointless,

Only because C doesn't have pass-by-reference.

> since in C you cannot hide anything behind a type - *encapsulation* is
> a completely alien concept to C.

Encapsulation is orthogonal to pass-by-(value or reference).

> The programmer is provided with
> access to a linear address space, gives type-level interpretations to
> data existing in the linear address space, and writes functions
> manipulating the data - that's all there is in C.

And?

> In my opinion, Go values of type interface{} encapsulating a pointer
> to an object are passing the object by reference.

They're pointing to it, just as pointers not hidden behind
interface{} are. That doesn't make it "passing the object by
reference".

unread,
Nov 30, 2011, 7:16:44 AM11/30/11
to golang-nuts
On Nov 30, 12:53 pm, r2p2 <robert-pet...@gmx.net> wrote:
> No I think not. If I declare a method as const then the compiler will not
> allow calling a non-const method on that object (from inside the const
> method).

The compiler will allow it if you find a non-const reference to the
object.

r2p2

unread,
Nov 30, 2011, 7:27:10 AM11/30/11
to golan...@googlegroups.com
Ok, there are always ways to shoot yourself in the foot.

Jonathan Amsterdam

unread,
Nov 30, 2011, 9:12:10 AM11/30/11
to golang-nuts
Consult any elementary programming language text for definitions of
call by value, reference, value-result, name, need. They are all
distinct, well-defined, and represented in at least one real
programming language.

unread,
Dec 1, 2011, 4:06:32 AM12/1/11
to golang-nuts, ehog....@googlemail.com
On Nov 30, 3:12 pm, Jonathan Amsterdam <jbamster...@gmail.com> wrote:
> Consult any elementary programming language text for definitions of
> call by value, reference, value-result, name, need. They are all
> distinct, well-defined, and represented in at least one real
> programming language.

I took your advice, and it helped.

But, it seems Go isn't a purely call-by-value language (http://
en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value). Example:

var buf bytes.Buffer
buf.WriteString("aaa")
buf.WriteString("bbb")

WriteString is declared as:

func (b *Buffer) WriteString(s string) (n int, err os.Error)

David Symonds

unread,
Dec 1, 2011, 4:18:08 AM12/1/11
to ⚛, golang-nuts, ehog....@googlemail.com
On Thu, Dec 1, 2011 at 8:06 PM, ⚛ <0xe2.0x...@gmail.com> wrote:

> On Nov 30, 3:12 pm, Jonathan Amsterdam <jbamster...@gmail.com> wrote:
>> Consult any elementary programming language text for definitions of
>> call by value, reference, value-result, name, need. They are all
>> distinct, well-defined, and represented in at least one real
>> programming language.
>
> I took your advice, and it helped.
>
> But, it seems Go isn't a purely call-by-value language (http://
> en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value). Example:
>
>  var buf bytes.Buffer
>  buf.WriteString("aaa")
>  buf.WriteString("bbb")
>
> WriteString is declared as:
>
>  func (b *Buffer) WriteString(s string) (n int, err os.Error)

What's not call-by-value there? Remember that
buf.WriteString("aaa")
is actually only syntactic sugar for
(&buf).WriteString("aaa")
so the receiver is a pointer being passed by value.


Dave.

chris dollin

unread,
Dec 1, 2011, 4:18:36 AM12/1/11
to ⚛, golang-nuts
On 1 December 2011 09:06, ⚛ <0xe2.0x...@gmail.com> wrote:
> But, it seems Go isn't a purely call-by-value language (http://
> en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value). Example:
>
>  var buf bytes.Buffer
>  buf.WriteString("aaa")
>  buf.WriteString("bbb")
>
> WriteString is declared as:
>
>  func (b *Buffer) WriteString(s string) (n int, err os.Error)

There's an explicit provision in the spec for a method
call x.f(WHATEVER) where f is defined on *T, x is of type T,
and x is addressable: it is shorthand for (&x).f(WHATEVER).

So yes, I'd be willing to say that Go was call-by-reference for
receivers of type T with methods wanting *T -- although my
preference would be to say it's call-by-value but there's
a special &-insertion rule. Either way there's some non-general
behaviour there.

unread,
Dec 1, 2011, 6:34:11 AM12/1/11
to golang-nuts, ehog....@googlemail.com
On Dec 1, 10:18 am, David Symonds <dsymo...@golang.org> wrote:

> On Thu, Dec 1, 2011 at 8:06 PM, ⚛ <0xe2.0x9a.0...@gmail.com> wrote:
> > But, it seems Go isn't a purely call-by-value language (http://
> > en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value). Example:
>
> >  var buf bytes.Buffer
> >  buf.WriteString("aaa")
> >  buf.WriteString("bbb")
>
> > WriteString is declared as:
>
> >  func (b *Buffer) WriteString(s string) (n int, err os.Error)
>
> What's not call-by-value there? Remember that
>   buf.WriteString("aaa")
> is actually only syntactic sugar for
>   (&buf).WriteString("aaa")
> so the receiver is a pointer being passed by value.
>
> Dave.

I think we should stop this discussion unless somebody presents a
mathematically precise definition of the term "call-by-value".

In any case, this discussion has probably no relation to the original
question in this forum thread: "Does it means string is passed to
function by value?"

In my opinion, the original question is about string as an object. The
question is asking whether the whole string object gets copied when
passing it to a function. In this sense, the correct answer would be:
strings are passed by reference.

Jan Mercl

unread,
Dec 1, 2011, 6:51:10 AM12/1/11
to golan...@googlegroups.com
On Thursday, December 1, 2011 12:34:11 PM UTC+1, ⚛ wrote:

In any case, this discussion has probably no relation to the original
question in this forum thread: "Does it means string is passed to
function by value?"

In my opinion, the original question is about string as an object. The
question is asking whether the whole string object gets copied when
passing it to a function. In this sense, the correct answer would be:
strings are passed by reference.

The built in string type is a value type. Variables (also function/method arguments from now on) and struct fields of type string are passed/copied by value. A string value ('var s string' vs "abc") is (simplified) a []byte object, which is referenced by the string typed variable/field, but that's not in conflict with string being a value type - as also e.g. interfaces, slices, ... are. Note those also do/may internally hold a reference to some other entity/ies.

chris dollin

unread,
Dec 1, 2011, 6:53:16 AM12/1/11
to ⚛, golang-nuts
On 1 December 2011 11:34, ⚛ <0xe2.0x...@gmail.com> wrote:

> I think we should stop this discussion unless somebody presents a
> mathematically precise definition of the term "call-by-value".

What would that ("the mathematically precise") give us other
than arguments about whether that was the right definition?

"Call by value", better "pass by value", means that formal
argument x is a copy of the corresponding actual argument
value: updates to x do not affect the argument.

Note that this says updates /to/ x, not updates /via/ x. x
may contain (or be) a reference (or pointer) to some other
entity (variable, location) and assigning through (dereferencing)
that that reference may be visible by dereferencing the
corresponding reference in the actual argument value: that
doesn't count for the purpose of calling something "pass by value".
(Otherwise you could never say of a pointer that it was passed
by value, which would be unhelpful, especially since there
are pointers passed by reference and those would be different.)

> In any case, this discussion has probably no relation to the original
> question in this forum thread: "Does it means string is passed to
> function by value?"
>
> In my opinion, the original question is about string as an object.

What does that mean, "as an object"?

> The
> question is asking whether the whole string object gets copied when
> passing it to a function.

Is it? What does "whole string" mean? Does it include the
reference to the underlying bytes or not?

> In this sense, the correct answer would be:
> strings are passed by reference.

The correct answer is "by value", because nothing you can
do to the formal parameter can safely change the value of the
actual argument /at all, ever/, because the (referred to,
shared) underlying bytes can't be updated.

The rider is "and cheaply, because the bytes of the string's
spelling are shared via references".

That still doesn't make it pass-by-reference.

Volker Dobler

unread,
Dec 1, 2011, 8:19:49 AM12/1/11
to golang-nuts
That does not depend on the compiler: const_cast is a language
feature.
Const methods in C++ provide some kind of "feeling" of safty than real
production strength safty.

On Nov 30, 12:53 pm, r2p2 <robert-pet...@gmx.net> wrote:

unread,
Dec 1, 2011, 12:01:17 PM12/1/11
to golang-nuts
I am giving up.

On Dec 1, 12:53 pm, chris dollin <ehog.he...@googlemail.com> wrote:

Greg Miller

unread,
Dec 3, 2011, 11:46:44 AM12/3/11
to golang-nuts
On Nov 30, 5:57 am, chris dollin <ehog.he...@googlemail.com> wrote:

> On 30 November 2011 11:31, ⚛ <0xe2.0x9a.0...@gmail.com> wrote:
> > ... I am highly confused by your naming convention ...
>
> For pass-by-value (aka call-by-value)? As far as I'm aware, it's
> pretty much the traditional one.
>
> > Under your naming convention, all programming languages are pass-by-
> > value.
>
> Not true. Both Pascal and C++ can do pass-by-reference
> (Pascal with VAR parameters, C++ with references).
> Algol 60 has pass-by-"name". Algol68 can be viewed that
> way.
>
> > If all of them are pass-by-value, there would be no point to
> > use this term - it has no power to distinguish.
>
> Indeed.
>
> > In my opinion, Java is pass-by-reference (except for low-level types
> > such as "int").
>
> No, Java is a pass-by-value language. HOWEVER, the non-primitive
> values are all references to "objects", and getting at fields of
> objects does an implicit dereference.

I don't see the distinction you're drawing between Java and C++ here.
My understanding has always been that C++ was considered a pass-by-
value language. You can pass reference types by value (just like Java)
and C++ allows a reference type for every corresponding value type,
but it doesn't use any special syntax or features for function
declarations (unlike Pascal). The only difference I see between C++
and Java is that Java forces certain types to be references and forces
others to be values, while value and reference types are allowed for
any data in C++.

Greg Miller

unread,
Dec 3, 2011, 12:08:02 PM12/3/11
to golang-nuts
On Dec 1, 5:34 am, ⚛ <0xe2.0x9a.0...@gmail.com> wrote:
> I think we should stop this discussion unless somebody presents a
> mathematically precise definition of the term "call-by-value".

I would say that a language is call-by-reference if value or reference
semantics can be selected without changing anything else (such as the
type of the data), and call-by-value otherwise. So, C, C++, Java, and
Go are call-by-value, while Pascal and Visual Basic are call-by-
reference.

Kyle Lemons

unread,
Dec 3, 2011, 11:16:42 PM12/3/11
to Greg Miller, golang-nuts
I would say that a language is call-by-reference if value or reference
semantics can be selected without changing anything else (such as the
type of the data), and call-by-value otherwise. So, C, C++, Java, and
Go are call-by-value, while Pascal and Visual Basic are call-by-
reference.

(in C++, you can add a & on the function side and make it a reference without touching any callers)

chris dollin

unread,
Dec 5, 2011, 2:56:39 AM12/5/11
to Greg Miller, golang-nuts
On 3 December 2011 16:46, Greg Miller <gregl...@gmail.com> wrote:
> On Nov 30, 5:57 am, chris dollin <ehog.he...@googlemail.com> wrote:
>> On 30 November 2011 11:31, ⚛ <0xe2.0x9a.0...@gmail.com> wrote:
>> > ... I am highly confused by your naming convention ...
>>
>> For pass-by-value (aka call-by-value)? As far as I'm aware, it's
>> pretty much the traditional one.
>>
>> > Under your naming convention, all programming languages are pass-by-
>> > value.
>>
>> Not true. Both Pascal and C++ can do pass-by-reference
>> (Pascal with VAR parameters, C++ with references).
>> Algol 60 has pass-by-"name". Algol68 can be viewed that
>> way.
>>
>> > If all of them are pass-by-value, there would be no point to
>> > use this term - it has no power to distinguish.
>>
>> Indeed.
>>
>> > In my opinion, Java is pass-by-reference (except for low-level types
>> > such as "int").
>>
>> No, Java is a pass-by-value language. HOWEVER, the non-primitive
>> values are all references to "objects", and getting at fields of
>> objects does an implicit dereference.
>
> I don't see the distinction you're drawing between Java and C++ here.

Summary: in Java, all argument passing is by value, but in C++, some
argument passing is by reference.

If `i` is an integer variable, in Java the method call wossname(i) can't
change the value of i by updating the parameter. In C++, if the parameter
is a reference-to-int, it can.

The same is true for bool, long, etc. It's also true for Java's reference
values: you can't change the value of the /reference/ by updating
a parameter but you can change the value of the thing /referred to/.

> My understanding has always been that C++ was considered a pass-by-
> value language.

Except for the thing about references.

> You can pass reference types by value (just like Java)
> and C++ allows a reference type for every corresponding value type,
> but it doesn't use any special syntax or features for function
> declarations (unlike Pascal). The only difference I see between C++
> and Java is that Java forces certain types to be references and forces
> others to be values, while value and reference types are allowed for
> any data in C++.

C++ has pass-by-reference as an option, by having the parameter
type be an &T (for whatever T) and having implicit conversions from
variable-of-type-T to &T and the reverse. You're right that C++'s machinery
isn't tied to parameter passing, but it's not just the general use of
the reference mechanism that distinguishes it from Java, it's the
automatic conversion from reference to value (Java's [un]boxing is
a sort-of approximation to it, though).

pass-by-value vs pass-by-reference distinguishes, in a call f(x) to
a function defined with f(xparam){...}, whether assigning to xparam
updates x (xparam is a reference to x) or does not (xparam is a copy
of x). Languages with implicitly-dereferenced references make "copy of"
a bit less obvious, and one could argue that the by-ref/value division
is less useful nowadays when such languages are more widespread,
but that's the heart of the distinction.

(Note that pass-by-whatever applies to a particular argument position
of a function: in general some arguments may by by-value and others
by-reference [and others may be pass-by-result or pass-by-procedure or
pass-by name ...]. To say of a /language/ that it's call-by-value or
call-by-reference would suggest that all of its arguments are passed
by-value or by-reference. That would make Java a pass-by-value
language, C++ neither (since you get a free choice at each argument
position) but you can say "by value except ..." with a complicated
clause about when variables become references, Go by-value [except for
addressable receivers passed to methods on pointer receivers] and
C entirely pass-by-value [because the trick where arrays decay into
pointers isn't part of the sematics of argument-passing].

In short, it's perfectly straightforward -- apart from the details ...

Chris

--
Chris "" Dollin

Greg Miller

unread,
Dec 5, 2011, 6:03:15 PM12/5/11
to golan...@googlegroups.com

But not without changing the type of the parameter from a value type
to a reference type. This is fundamentally the same as in Java, except
that Java makes certain types (objects) available only as reference
types and others (scalar numbers, for example) available only as value
types. The "&" isn't any kind of special feature or syntax that
applies specifically to function calls. C++ just allows the implicit
conversion from from int to int &, so that you don't have to do things
like:

void f(int &a) { a = 1; }

int main() {
int i = 0;
int &j = i;
f(j);

return i;
}

In other words, passing a reference type by value allows you to use
reference semantics in both languages and passing a value type by
value gives you value semantics in both languages.

Reply all
Reply to author
Forward
0 new messages