Live data from Hacker News

Go structs are copied on assignment (and other things about Go I'd missed)

jvns.ca

51–60 of 176 posts

Re: Go structs are copied on assignment (and other things about Go I'd missed)

#51
post #43
post #30

Earlier quoted context omitted.

Is python no longer a modern language? Objects are certainly not copied when passed to a function.

Python copies references by value. $ python3 Python 3.12.3 (main, Jul 31 2024, 17:43:48) [GCC 13.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> def x(): ... v = 1 ... y(v) ... print(v) ... >>> def y(val): ... val += 1 ... >>> x() 1 A pass-by-reference language would print 2. Everything in a modern language is passed by copy. Exactly what is copied varies and can easily be poi…

uh I'd not say it like that

Python passes primitive types by value, out rather "as if by value", because it copies them on write.

if you modify your experiment to pass around a dict or list and modify that in the 'y', you'll see y is happily modified.

so Python passes by reference, however it either blocks updates (tuple) or copies on write (int, str, float) or updates in place (dict, list, class)

Re: Go structs are copied on assignment (and other things about Go I'd missed)

#52
post #18

Earlier quoted context omitted.

As she points out though, a lot of dynamic languages don’t behave this way. A string after all points to a heap allocation; so it’s not unreasonable to think of a string as a pointer.

It’s how structs work in C though, and Go is spiritually very close to C, including explicit pointer types, address-taking and dereferencing.

Not necessarily. A string in C is usually a char. If you have a struct with a char and you copy it, you copy the pointer to the backing memory. This is analogous to Go which also has a String be a pointer to the heap, but the behavior is different.

Go’s String is a char* that behaves like a char[] when copied.

Re: Go structs are copied on assignment (and other things about Go I'd missed)

#53
The semantics of when stuff is copied, moved, or passed by reference are all over the place in language design.

C started with the idea that functions returned one int-sized value in a register. This led to classic bugs where the function returns a pointer to a local value. Compilers now usually catch this. C eventually got structure return by copy. Then C++ added return value by move, and automatic optimization for that. It's complicated.[1]

Most hard-compiled languages only let you return values of fixed length, because the caller has to allocate space. Dynamic languages where most things are boxed just return the box. Rust makes you declare boxed types explicitly. Vec and String are already boxed, which handles the common cases.

More dynamic languages tend to let you return anything, although there can be questions over whether you have your own mutable copy, a copy-on-write copy, a read-only copy, or a mutable reference to the original. That's what got the OP here, at

    thing := findThing(things, "record")
    thing.Name = "gramaphone"
They thought they had a mutable reference to the original, but they had a mutable copy.

There's a good argument for immutability by default, but many programmers dislike all the extra declarations required.

[1] https://stackoverflow.com/questions/17473753/c11-return-valu...

Re: Go structs are copied on assignment (and other things about Go I'd missed)

#54
post #18

Earlier quoted context omitted.

It’s how structs work in C though, and Go is spiritually very close to C, including explicit pointer types, address-taking and dereferencing.

Not necessarily. A string in C is usually a char . If you have a struct with a char and you copy it, you copy the pointer to the backing memory. This is analogous to Go which also has a String be a pointer to the heap, but the behavior is different. Go’s String is a char* that behaves like a char[] when copied.

> Go’s String is a char* that behaves like a char[] when copied.

Uhh, no. A go string is (effectively) a pointer to an immutable string of characters. When you do a = b, both a and b point to the same string (i.e. each is its own string struct, containing a pointer to the exact same array of character data).

But if you try to get a byte[] from it, THEN it makes a copy.

Re: Go structs are copied on assignment (and other things about Go I'd missed)

#55

To generalize the title into a rule is good to remember that in Go everything is passed by value(copy).

Maps and channels and functions are passed by reference. Slices are passed and returned by value but sometimes share state invisibly, the worst of both worlds. It would make more sense if Go either made this stuff immutable, made defensive copies, or refused and required using explicit pointers for all these cases.

No, it's not the case and this terminology shouldn't be used as it's confusing and unhelpful.

There are reference types in Go even though this is also not a super popular term. They still follow the pass-by-value semantics, it's just that a pointer is copied. A map is effectively a pointer to hmap data structure.

In the early days of Go, there was an explicit pointer, but then it was changed.

Slices are a 3-word structure internally that includes a pointer to a backing array and this is why it's also a "reference type".

That said, everything is still passed by value and there are no references in Go.

Re: Go structs are copied on assignment (and other things about Go I'd missed)

#56
post #28

This sometimes catches out people C#/.Net too, it's a big difference between Class and Struct, Class is reference type and Struct is value type. (see fiddle below), but in practice people very rarely reach for structs, so people don't tend to build up the muscle memory of using them, even if they intuitively understand the difference between reference types and value types from general use of other types. (Fiddle dem…

Non-C# developer question: what use-case/situation would a `struct` make sense to use instead of a `class`? Just out of curiosity. [Edit] Well, there's a nice, special article for this very question: https://learn.microsoft.com/en-us/dotnet/standard/design-gui...

Even if you exclude performance reasons, some things just make more sense as values rather than instances. A good example is Color. A Color might be an object that holds 3 integers (red, green, blue) but you want to treat it like you would a scalar value. For example, two color instances should be equal if they contain all the same values. Class instances all have their own identity -- two classes instances are not equal even if they contain the same values.

Re: Go structs are copied on assignment (and other things about Go I'd missed)

#57

Donovan and Kernighan's "The Go Programming Language" is one of the best pieces of technical writing I've ever read. Buy it and read it cover to cover. Then read the [Go Language Specification][1] cover to cover. It's dry but refreshingly not legalese. [1]: https://go.dev/ref/spec

Learning Go by Jon Bodner, particularly the newest edition, is also excellent. An aside: are there any other Go books, particularly ones the explore more specific topics, that are recommended? I've read a few that I didn't find very impressive.

I liked Cloud Native Go by Matthew A. Titmus and Concurrency in Go by Katherine Cox-Buday.

Re: Go structs are copied on assignment (and other things about Go I'd missed)

#58

Earlier quoted context omitted.

Maps and channels and functions are passed by reference. Slices are passed and returned by value but sometimes share state invisibly, the worst of both worlds. It would make more sense if Go either made this stuff immutable, made defensive copies, or refused and required using explicit pointers for all these cases.

No, it's not the case and this terminology shouldn't be used as it's confusing and unhelpful. There are reference types in Go even though this is also not a super popular term. They still follow the pass-by-value semantics, it's just that a pointer is copied. A map is effectively a pointer to hmap data structure. In the early days of Go, there was an explicit pointer, but then it was changed. Slices are a 3-word stru…

You are splitting hair, Maps are effectively references.

That's like saying C++ doesn't have references since it's just a pointer being copied around

Re: Go structs are copied on assignment (and other things about Go I'd missed)

#59
post #43
post #30

Earlier quoted context omitted.

Is python no longer a modern language? Objects are certainly not copied when passed to a function.

Python copies references by value. $ python3 Python 3.12.3 (main, Jul 31 2024, 17:43:48) [GCC 13.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> def x(): ... v = 1 ... y(v) ... print(v) ... >>> def y(val): ... val += 1 ... >>> x() 1 A pass-by-reference language would print 2. Everything in a modern language is passed by copy. Exactly what is copied varies and can easily be poi…

C++ is a live language, C# has out parameters.... there's stuff out there.

The classic example of "pass by copy-reference is less expressive" is you can't have pass a reference to number and have the caller modify it. You have to explicitly box it. I understand you understand this, but it's worth considering when thinking about whether the distinction means absolutely nothing at all.

Re: Go structs are copied on assignment (and other things about Go I'd missed)

#60
post #53

The semantics of when stuff is copied, moved, or passed by reference are all over the place in language design. C started with the idea that functions returned one int-sized value in a register. This led to classic bugs where the function returns a pointer to a local value. Compilers now usually catch this. C eventually got structure return by copy. Then C++ added return value by move, and automatic optimization for…

> This led to classic bugs where the function returns a pointer to a local value. Compilers now usually catch this. C eventually got structure return by copy. Then C++ added return value by move, and automatic optimization for that.

Jesus Christ. Can we now get “return fruit by vegetable?”

Some speedups may not be worth having to memorize standards documents.

Post reply on HN