Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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


> , 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]




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: