Live data from Hacker News

In Go, pointers (mostly) don't go with slices in practice

utcc.utoronto.ca

11–20 of 98 posts

Re: In Go, pointers (mostly) don't go with slices in practice

#11
post #4

It would be more accurate to say that pointers don’t work with append() or any other way of growing an array, since they all depend on reallocating it sometimes. Incidentally, this is equally true of creating additional pointers or slices pointing into an growable array. They aren’t safe after the next append(). If you grow an array then you need to refer to its elements using array indices. But if you have a fixed-l…

> If you’re thinking of a slice as a JavaScript array then you’ll have trouble.

The problem of Go is that it has you uses slices as that as well as actual slices, there is no vector type. So the confusion is very much understandable and to be expected.

Re: In Go, pointers (mostly) don't go with slices in practice

#13
post #6

>Honestly, this is a strange and peculiar situation, although Go programmers have acclimatized to it. To programmers from other languages, such as C or C++, the concept of pointers to dynamically extensible arrays seems like a perfectly decent idea that surely should exist and work in Go. Well, it exists, and it "works" in the sense that it yields results and doesn't crash your program, but it doesn't "work" in the s…

C++ has std::vector, which is one level of abstraction above a slice; you push to a vector, and maybe the backing slice changes, but it's still the same vector.

Go is unusual in not having a equivalent of vector.

Re: In Go, pointers (mostly) don't go with slices in practice

#15
post #7
post #5

The author seems confused. The following is simply not true: When you take a pointer to a slice, you get a pointer to the current version of this tuple of information for the slice. This pointer may or may not refer to a slice that anyone else is using; for instance: ps := &s s = append(s, 50) At this point, '*ps' may or may not be the same thing as 's', and so it might or might not have the new '50' element at the e…

Yep, that immediately stood out to me too. s is a local variable (or global, doesn't matter). ps simply points to that local variable. You can modify the local variable all day long and ps will still point to it, not some old version of it.

the line `s = append(s, 50)` redefines what "s" actually is. And after this line `ps` points to some previous version of what "s" used to be.

Re: In Go, pointers (mostly) don't go with slices in practice

#16
post #3

Well, of course slices work that way. Think about what happens if you have a reference to a slice in an array and you shrank the array to 0. You've just created a dangling pointer. In Go, you get a stable version of the old data, and the garbage collector tracks that you still have a reference to it. This is safe, but confuses some people. In Rust, the borrow checker won't let you modify the array while you have a re…

> This is safe, but confuses some people. Rust has created a weird perception that memory safety equals safety. Language is a tool and it should work with me: it is extremely important that my understanding of what the program should do aligns with what it actually does. The way you describe go's behavior is "takes snapshot of the underlying data", which usually means "deep copy container". Taking a pointer/reference…

The problem here is identical to the problem of pointers to array elements in C after a 'realloc', except that Go at least guarantees that you're not going to modify some other object's memory.

Of course, since append neither guarantees nor prevents a copy, the semantics of modifying a value through a pointer to a slice element after an append are unspecified, so it is not a useful construct.

Re: In Go, pointers (mostly) don't go with slices in practice

#17
post #3

Well, of course slices work that way. Think about what happens if you have a reference to a slice in an array and you shrank the array to 0. You've just created a dangling pointer. In Go, you get a stable version of the old data, and the garbage collector tracks that you still have a reference to it. This is safe, but confuses some people. In Rust, the borrow checker won't let you modify the array while you have a re…

> This is safe, but confuses some people. Rust has created a weird perception that memory safety equals safety. Language is a tool and it should work with me: it is extremely important that my understanding of what the program should do aligns with what it actually does. The way you describe go's behavior is "takes snapshot of the underlying data", which usually means "deep copy container". Taking a pointer/reference…

> The way you describe go's behavior is "takes snapshot of the underlying data", which usually means "deep copy container".

There’s no need for Go to copy anything in the circumstance the OP described. It just doesn’t shrink the underlying array.

Re: In Go, pointers (mostly) don't go with slices in practice

#18
post #15
post #7

Earlier quoted context omitted.

Yep, that immediately stood out to me too. s is a local variable (or global, doesn't matter). ps simply points to that local variable. You can modify the local variable all day long and ps will still point to it, not some old version of it.

the line `s = append(s, 50)` redefines what "s" actually is. And after this line `ps` points to some previous version of what "s" used to be.

No, that line modifies the value of the variable s to represent the value of a new slice returned by append (assuming append did need to reallocate). Any pointer to s will point to this new value.

A variable in Go always maintains its address after it is allocated. Assignments to that variable copy the assigned value to the original address.

Somewhat unhelpfully, this rule is even true for iteration variable - when you write 'for i,v := range arr {...}', i and v get allocated a memory address, and they get successively assigned the indices and values in arr. This implies that each element in arr is copied into the value of v, and that doing &v inside the loop gives you a completely different pointer than &arr[i]. In fact, &v will always point to the last element of arr after the loop is over.

Re: In Go, pointers (mostly) don't go with slices in practice

#19
post #15
post #7

Earlier quoted context omitted.

Yep, that immediately stood out to me too. s is a local variable (or global, doesn't matter). ps simply points to that local variable. You can modify the local variable all day long and ps will still point to it, not some old version of it.

the line `s = append(s, 50)` redefines what "s" actually is. And after this line `ps` points to some previous version of what "s" used to be.

Did you check GP's link? It demonstrates that ps points to s, not any particular version of it.

Re: In Go, pointers (mostly) don't go with slices in practice

#20
post #15
post #7

Earlier quoted context omitted.

Yep, that immediately stood out to me too. s is a local variable (or global, doesn't matter). ps simply points to that local variable. You can modify the local variable all day long and ps will still point to it, not some old version of it.

the line `s = append(s, 50)` redefines what "s" actually is. And after this line `ps` points to some previous version of what "s" used to be.

No, ps still points to s:

https://play.golang.org/p/iSjoqGTg20_O

    var s []int
    s = append(s, 10, 20, 30)
    pe := &s[0]
    ps := &s
    s = append(s, 50)
    s[0] = 100
    pe2 := &s[0]
    fmt.Println("s: ", s, ", ps: ", ps, ", pe: ", pe, ", pe2: ", pe2)
    // s:  [100 20 30 50] , ps:  &[100 20 30 50] , pe:  0xc0000be000 , pe2:  0xc0000b8030
Post reply on HN