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...