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…
Go structs are copied on assignment (and other things about Go I'd missed)
161–170 of 176 posts
Re: Go structs are copied on assignment (and other things about Go I'd missed)
#162The 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…
Go and C are quite wise to use pass by value and opt-in references. It avoids the programmer's burden of immutability by default while making it more obvious* when to be aware of potential mutation. A programming style incorporating local mutation also comes very naturally, which is simple, practical, and remains easy to reason about.
*Go and Rust would be wiser if they retained -> from C so that this obviousness would remain without having to check type declarations which may even have been inferred.
Python gets hit the worst by this combination. On top of having mutable references everywhere, it also doesn't make a big deal about object identity (unlike e.g. Java) and has a lot of declarative constructs. Which means you get surprising stuff like this.
>>> foo = [[]] * 10
>>> foo[0].append("bar")
>>> foo
[['bar'], ['bar'], ['bar'], ['bar'], ['bar'], ['bar'], ['bar'], ['bar'], ['bar'], ['bar']]
>>> def baz(arg = []):
... print(arg)
... arg.append("qux")
...
>>> baz()
[]
>>> baz()
['qux']Re: Go structs are copied on assignment (and other things about Go I'd missed)
#163Earlier quoted context omitted.
Is it not pass-by-reference by some technicality? In the mutation example you suggest, if a reference to x isn't being passed into foo, how could foo modify x? I would sooner believe the example is showing you shadowing the z argument to foo, than foo being able to modify the in-parameter sometimes even if it's pass by value.
> In the mutation example you suggest, if a reference to x isn't being passed into foo, how could foo modify x The important point is that it's not "a reference to x" that gets passed, it's a copy of x's value. x's value, like the value of all Python variables, is a reference to some object. The same thing applies to setting variables in Python in general: x = {1:2} # x is a new variable that references some dict y =…
so we disagree on terminology?
in my CS upbringing, sharing the memory location of a thing as parameter was tagged "call by reference". the hallmark was: you can in theory modify the referenced thing, and you just need to copy the address.
call by value, in contrast, would create an independent clone, such that the called function has no chance to modify the outside value.
now python does fancy things, as we both agree. the result of which is that primitives (int, flot, str) behave as if they were passed by value, while dict and list and its derivatives show call by reference semantics.
I get how that _technically_ sounds like call by value. and indeed there is no assignment dunder. you can't capture reassignment of a name.
but other than that a class parameter _behaves_ like call by reference.
Re: Go structs are copied on assignment (and other things about Go I'd missed)
#164Not understanding structs vs pointers is a pretty basic misconception in go. Does this trip anyone else up? I found it unenlightening / unsurprising, and the linked "100 mistakes" piece also very basic and in some cases just plain wrong.
Re: Go structs are copied on assignment (and other things about Go I'd missed)
#165Not understanding structs vs pointers is a pretty basic misconception in go. Does this trip anyone else up? I found it unenlightening / unsurprising, and the linked "100 mistakes" piece also very basic and in some cases just plain wrong.
Please let me know what's plain wrong; I'm always happy to receive constructive feedback.
After trudging through more of the list, you've collected a lot of good nuggets! Maybe move the if-else to the end, as it's not particularly insightful compared to the rest.
Also the shadowing, it's fine but much less interesting and unlikely to hook in your target audience up front.
Good luck!
Re: Go structs are copied on assignment (and other things about Go I'd missed)
#166Earlier quoted context omitted.
> Actually Go is always pass by value. False, this depends upon the underlying type. The Go 'map' type is always pass (and assign) by reference. https://go.dev/play/p/ovfuNBNtiza
Technically no, but I get why it feels like this. :-) I think the confusion stems from the fact that Go hides the distinction of "dot" access vs "pointer dot" access. (eg, the difference between `foo.Bar` and `foo->Bar` in C++). Go knows if an object is a pointer and needs to be de-referenced, and hides the de-reference operation from you syntactically. So you can use a pointer without knowing it's a pointer. This is…
> Map types are reference types, like pointers or slices.
Re: Go structs are copied on assignment (and other things about Go I'd missed)
#167Earlier quoted context omitted.
That is the case for almost every modern language. C++ is one of the few languages that has "references" and at least last I looked that's a language accommodation over what are pointers being passed by value in the assembly, at least until compiler optimizations take over (and that's not limited to references either). If you're in 2024 and you're in some programming class making a big deal about pass-by-value versus…
Sure, if they want to be bad developers in C#, F#, Swift, D, Rust, Ada, VB, Delphi, just to stay on the ones that are kind of relevant in 2024 for business, for various level of relevant, versus the ones story has forgotten about.
#include
#include
void s_ref_modify(std::string& s)
{
s = std::string("Best");
return;
}
int main()
{
std::string str = "Test";
s_ref_modify(str);
std::cout
The equivalent Rust requires passing a mutable pointer to the callee, where it is explicitly dereferenced: fn s_ref_modify(s: &mut String) {
*s = String::from("Best");
}
fn main() {
let mut str = String::from("Test");
s_ref_modify(&mut str);
println!("{}", str);
}
Swift has `inout` parameters, which superficially look similar to pass-by-reference, except that the semantics are actually copy-in copy-out[2]:> In-out parameters are passed as follows:
> 1. When the function is called, the value of the argument is copied.
> 2. In the body of the function, the copy is modified.
> 3. When the function returns, the copy’s value is assigned to the original argument.
> This behavior is known as _copy-in copy-out_ or _call by value result_. For example, when a computed property or a property with observers is passed as an in-out parameter, its getter is called as part of the function call and its setter is called as part of the function return.
[1]: https://doc.rust-lang.org/book/ch04-02-references-and-borrow...
[2]: https://docs.swift.org/swift-book/documentation/the-swift-pr....
Re: Go structs are copied on assignment (and other things about Go I'd missed)
#168Earlier quoted context omitted.
Technically no, but I get why it feels like this. :-) I think the confusion stems from the fact that Go hides the distinction of "dot" access vs "pointer dot" access. (eg, the difference between `foo.Bar` and `foo->Bar` in C++). Go knows if an object is a pointer and needs to be de-referenced, and hides the de-reference operation from you syntactically. So you can use a pointer without knowing it's a pointer. This is…
From Google's Go project blog: > Map types are reference types, like pointers or slices. https://go.dev/blog/maps
References are nothing special, they are are simply pointers that hide the pointer and usually the receiving definition makes the decision about whether a pointer of a copy is passed.
In Go the type is just a wrapper around a pointer, making it function like a reference in all cases.
In go some types are simply defined as pointers, so they are technically always passed by value and there is never any magic about whether they are passed by value or referenced. It is always a value consisting of a reference.
A map is a pointer that is passed by value, along with slices and channels. 100% of the time.
Re: Go structs are copied on assignment (and other things about Go I'd missed)
#169Earlier quoted context omitted.
I hope it gets added, it adds so much safety to the language. Mind you, Go is not a very safe language in general, its type system is pretty loose compared to e.g. Java or Typescript. I don't believe it wants to be though.
It is possible to add more immutability in Go. There are many proposals for this: https://github.com/go101/go101/wiki/Go-immutable-value-propo... . The main reason nothing happened in this direction is the core team think it is not important enough.
Re: Go structs are copied on assignment (and other things about Go I'd missed)
#170Earlier quoted context omitted.
It is possible to add more immutability in Go. There are many proposals for this: https://github.com/go101/go101/wiki/Go-immutable-value-propo... . The main reason nothing happened in this direction is the core team think it is not important enough.
It's very clear that the reason these kinds of proposals haven't been accepted has nothing to do with the core team not believing they're important enough, but instead because of the impact that they have on the rest of the language.