6 ms·
thing := Thing{...} other_thing := thing pinter_to_same_thing := &thing ALL types in go are being copied by value. There is no such thing as a "referen
by usrbinbash 2y ago
thing := Thing{...}
other_thing := thing
pinter_to_same_thing := &thing
ALL types in go are being copied by value. There is no such thing as a "reference" in this language. Even a slice or map is just a small struct with some syntactic sugar provided by the language, and when you assign a slice to another variable, you are, in fact, creating a copy of that struct.
- uniq7 2y agoMy pet peeve with slices and maps is that they hide a reference to the actual structure, and you are never sure of what you are modifying, or the performance impact when moving around big structures. Example with slices: https://go.dev/play/p/8arcUrGU4SU https://go.dev/play/p/8arcUrGU4SU Example with maps: https://go.dev/play/p/eq8i6z8a4jN https://go.dev/play/p/eq8i6z8a4jN
- usrbinbash 2y agoNo, there is no "hiding" of a "reference". There is copying a struct: s2 := s1 This copies the struct in `s1` into a new name `s2`. This struct contains, among other things, a pointer to the backing array. Therefore, when you assign to the slice s2[0] = "bye" You assign to the same backing array. Slices are not arrays. Copying a slice copies a struct containing a pointer to an array. A similar situation holds true for maps. The same logic that is universal throughout the language, aka. "Go only ever copies things by value" holds true for all of these types. https://go.dev/ref/spec#Slice_types https://go.dev/ref/spec#Slice_types "A slice, once initialized, is always associated with an underlying array that holds its elements. A slice therefore shares storage with its array and with other slices of the same array; by contrast, distinct arrays always represent distinct storage."
- Joker_vD 2y agoSince a slice/map, internally, contains a pointer to the data, it looks like slices/maps have reference semantics: after you do "m2 := m1", all changes done through m1 are visible through m2, even though the type of m1 and m2 has no visible asterisk anywhere in it.
- usrbinbash 2y ago> , it looks like slices/maps have reference semantics No, they don't. Pointers and references are fundamentally different concepts. A reference is a name, handled by the runtime, that is bound to an entity. A pointer is just a value of type `uintptr`. When I "copy" a reference, I simply instruct the runtime to bind another name to the entity. When I copy a struct containing a pointer, I actually allocate new memory to contain a new copy of that `uintptr`. And since that copy is a true copy of a pointer-value, I can change it. That's why this: func main() { s1 := []int{1, 2} s2 := s1 s2 = append(s2, 3) s1[0] = 42 fmt.Println(s1) fmt.Println(s2) } Will give you [42 2] [1 2 3] as an output. s2 is not a "Reference" to the same entity as s1, it is a struct holding a pointer, and when we grow the slice this struct represents beyond the capacity of the backing array that pointer points to, by appending to it, we replace that pointer in s2. Comparing that to a language that actually does have reference semantics (python): s1 = [1, 2] s2 = s1 s2.append(3) s1[0] = 42 print(s1) print(s2) Gives me [42, 2, 3] [42, 2, 3]