3 ms·
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
by Thorrez 5y ago
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.
- watt 5y agothe 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.
- tsimionescu 5y agoNo, 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.
- hvdijk 5y agoDid you check GP's link? It demonstrates that ps points to s, not any particular version of it.
- drran 5y agoNo, ps still points to s: https://play.golang.org/p/iSjoqGTg20_O 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
- watt 5y agoI don't get why address of slice returned from "append" does not change. Maybe in a trivial program like this the backing array can always be extended in-place, because there in memory fragmentation. Is that still true in an app that has considerable memory pressure and has GC running now and then?
- pitkali 5y agoEven if slice is reallocated, the information about new reallocated slice is still stored in variable s. ps is merely pointing to that variable. The fact that the contents of the variable changed does not mean that its location has to change. In other words, ps is a pointer to a pointer to array data. Append may change the inner pointer's value but that's about it.
- ubercow13 5y agos changes but &s doesn't: https://play.golang.org/p/Xs1SYXqEl9i https://play.golang.org/p/Xs1SYXqEl9i
- unrealhoang 5y agoBecause there’s still space left in that slice (capacity > len), and the strategy of pre allocate capacity is to double the current (1,2,4,8,…), in this case 3 elements added => that slice was having a capacity of 4.
- Thorrez 5y agoNo, you can see that it was reallocated. At first the backing array started at 0xc0000be000. The append needed to do a reallocation and created a new backing array that starts at 0xc0000b8030.
- _ph_ 5y agoAppend returns a value, the new slice struct generated by append. Append always generates a new struct and returns it by value, because even if the array pointed to doesn't change, the length property of the slice changes. This value is then assigned to the local variable s, which didn't change its memory location.
- boomlinde 5y ago`s` is some value that occupies some memory, starting at say address 1000. `ps` contains the address of `s`, 1000. It will do this no matter what you put in memory at address 1000. You can assign new values to `s`, e.g. via append, but ps will still point to its address, 1000. The confusion stems from the fact that a slice object contains a pointer in itself, pointing to a backing array, thus adding an additional layer of indirection. Append will return a new slice that may point to a different backing array. This doesn't matter, because you put the new slice in the memory location pointed at by ps, 1000. This is not so different from pointer pointers. If you have `int i = 0; int pi = &i; int *ppi = π` you can change `pi` (analogous to the slice) to your heart's content and `ppi` will reflect the changes.