Go: proposal: Go 2: don't allow taking address of slice elements

Created on 18 Nov 2019  路  8Comments  路  Source: golang/go

What version of Go are you using?

Playground

m := make(map[string]int, 0)
val := &m["foo"]

This will result in cannot take the address of m["foo"], because the location of elements in memory is not constant. Makes sense.

However it's allowed in slices:

    vals := []int{1, 2, 3, 4, 5}
    val := &vals[0]
    fmt.Printf("Val is: %v \n", *val)
    vals[0] = 10
    fmt.Printf("New Val is: %v \n", *val)
    vals = append(vals, 6)
    vals[0] = 11
    fmt.Printf("New Val is: %v \n", *val)

Output:

Val is: 1 
New Val is: 10 
New Val is: 10 

https://play.golang.org/p/7WlNtmOKS6f

As you can see, after the growth of the slice, there's reallocation, and val now points to the old data.

Go2 LanguageChange Proposal Proposal-FinalCommentPeriod

Most helpful comment

That example is OK if the code knows that the slice is long enough. And it's OK if the code doesn't need to change the value and expect the pointer to point to the new value.

All 8 comments

Please change title to Go should not allow taking an address of an element of slices, just like it already does with maps.
I miss understand your meaning.. I thought it is taking an address of []int{}.
I think golang also should taking an address of 10.

I don't see any way we could impose this restriction at this point. Taking the address of slice elements is pervasive.

If you don't use append, taking the address of slice elements is perfectly reasonable. Even allowing for append, the semantics are well-defined and predictable by the programmer. Unlike with maps, where the runtime decisions to move keys and values around inside the map are not under the programmer's control.

Is it ok to take the address of array elements?

 var x [10]int
 p := &x[0]

But this code is not ok?

 var x [10]int
 p := &x[:][0]

Could _go vet_ catch v = &s[i]; s = append(s, x); use_of(v) ?

That example is OK if the code knows that the slice is long enough. And it's OK if the code doesn't need to change the value and expect the pointer to point to the new value.

I turned this into a proposal, but it seems very unlikely that it would be accepted. It would break far too much existing and working code.

Please take a look at this line
~~go
vals = append(vals, 6)
~
~
What does this? You can not assume that vals is the same as before this assignment. vals will usualy be a copy of vals with an appended 6. Your address of vals[0] is still the address of your original vals, before you changed its value. I just played in the playground and added a "pointer" to the seccond element. Then I saw it. If You reassign val by
~~go
val = &vals[0]
~
~
after You gave vals a new value, then everything works like expected and the gc can clean up Your old vals and val.

And maybe you do something different:
~~go
newVals = append(vals, 6)
~
~
Would You expect that Your first element on vals has the same address as the first element in newVals? - I do not hope.

As noted above, this would break too much existing code, with no corresponding benefit or alternative implementation. And this issue does not have much support according to emoji voting. For these reasons, this is a likely decline. Leaving open for four weeks for final comments.

-- for @golang/proposal-review

No further comments.

Was this page helpful?
0 / 5 - 0 ratings