reflect.Slice on arrays: restrictions

1,581 views
Skip to first unread message

Dan Kortschak

unread,
Jan 31, 2013, 6:27:29 AM1/31/13
to golan...@googlegroups.com
Why is it not possible to reflect.Value.Slice() on an unaddressable array? This undoubtedly going to simple, but I don't understand it.

http://play.golang.org/p/23gm1OIAWp

And I guess a related question which will probably answer the first, 'What exactly is an addressable array?' It isn't clearly defined in the reflect documentation (and the restriction on Slice isn't noted except in the source), and though I have seen arrays that are addressable by virtue of the fact that they can be .Sliced, but I can't see what makes them different (a pointer to an array can not be sliced as it is not an array).

thanks
Dan

David DENG

unread,
Jan 31, 2013, 6:57:18 AM1/31/13
to golan...@googlegroups.com
I'm not sure whether this is a bug, but the following lines works:


This is similar to setting the value of a variable through refection.
David

Dan Kortschak

unread,
Jan 31, 2013, 7:31:49 AM1/31/13
to David DENG, golan...@googlegroups.com
OK, that sort of helps me think about it. That's just a wrapped call to
.Elem on a pointer. So it looks like the restriction is a reflect simulation of this:

http://play.golang.org/p/cwQhN-b0Kv

But why? The represented value stored by the reflect.Value does have an address in this case - maybe reflect can't get to it. That seems to be the case from this:

http://play.golang.org/p/5jYBPK2ydm

but I don't have access to unsafe right now, so I can't follow that.

Dan

On 31/01/2013, at 10:27 PM, "David DENG" <david...@gmail.com> wrote:

> http://play.golang.org/p/eGtviStCYL

David DENG

unread,
Jan 31, 2013, 7:34:08 AM1/31/13
to golan...@googlegroups.com, David DENG
By passing value (of slice), it is surely not addressable.

What I can't understand is why not being addressable prevents it from slicing.

David

Dan Kortschak

unread,
Jan 31, 2013, 7:53:04 AM1/31/13
to David DENG, golan...@googlegroups.com, David DENG
But the interface storing the represented value needs to point to the array, since it's too large to store. So it should know where it is, but clearly the pointer half of the interface is not the same as the address of the array:

http://play.golang.org/p/M8F-YY0gVc

What is the pointer half of the interface containing here? Russ's article doesn't seem to help me out since uses small values as examples.

On the second point, if you don't have the address, you can't fill the pointer of the slice header.

I think I've exhausted my reasoning on this. It is almost clear, but if someone with more knowledge could fill in the gaps, that would be nice.

Dan

Ian Lance Taylor

unread,
Jan 31, 2013, 2:24:27 PM1/31/13
to Dan Kortschak, golan...@googlegroups.com
On Thu, Jan 31, 2013 at 3:27 AM, Dan Kortschak
<dan.ko...@adelaide.edu.au> wrote:
> Why is it not possible to reflect.Value.Slice() on an unaddressable array? This undoubtedly going to simple, but I don't understand it.
>
> http://play.golang.org/p/23gm1OIAWp

A slice gives you another view into an existing array. When you
reflect on array by value, you are passing in a copy of the array
value, not the address of the array. A slice of that copy will give
you another view into that copy. This is a confusing notion: you've
got a slice of an array, but you don't have the array itself. You're
right that it could be implemented, but the result is potentially
confusing.

In any case the reflection rules simply restate the language rules.
You can not take a slice of an unaddressable value in the language
either:

http://play.golang.org/p/XyQxU5TDfg


> And I guess a related question which will probably answer the first, 'What exactly is an addressable array?' It isn't clearly defined in the reflect documentation (and the restriction on Slice isn't noted except in the source), and though I have seen arrays that are addressable by virtue of the fact that they can be .Sliced, but I can't see what makes them different (a pointer to an array can not be sliced as it is not an array).

The definition of addressable is in the language spec:
http://golang.org/ref/spec#Address_operators .

Ian

Dan Kortschak

unread,
Jan 31, 2013, 2:40:26 PM1/31/13
to Ian Lance Taylor, golan...@googlegroups.com
Thanks, Ian. The copying-not-being-reflected-back reason for the restriction make a lot of sense. Otherwise people might .Slice a reflected array, expecting that changes elements in the slice would be reflected in the original represented array passed to reflect.ValueOf.

On 01/02/2013, at 5:54 AM, "Ian Lance Taylor" <ia...@google.com> wrote:

> In any case the reflection rules simply restate the language rules.
> You can not take a slice of an unaddressable value in the language
> either:
>
> http://play.golang.org/p/XyQxU5TDfg

Yes, I figured that was part of it.

> The definition of addressable is in the language spec:
> http://golang.org/ref/spec#Address_operators .

Yes, I understand the notion of addressable, but it is subtly different here. Though now I can see why the similarities are important; as you say the though it could be implemented, it would be confusing.

Is it worth noting on the reflect.Slice documentation that an array must be addressable?

Dan

Ian Lance Taylor

unread,
Jan 31, 2013, 3:13:51 PM1/31/13
to Dan Kortschak, golan...@googlegroups.com
On Thu, Jan 31, 2013 at 11:40 AM, Dan Kortschak
<dan.ko...@adelaide.edu.au> wrote:
>
> Is it worth noting on the reflect.Slice documentation that an array must be addressable?

Yes, I think so.

Ian

David DENG

unread,
Jan 31, 2013, 7:26:43 PM1/31/13
to golan...@googlegroups.com, Dan Kortschak
I didn't notice it was an array, not a slice. If so, it has been clearly addressed in the document. In go, array is like a struct, so in the reflect article, it explans why you need it to be addressable.

David

Dan Kortschak

unread,
Feb 2, 2013, 4:26:28 PM2/2/13
to Ian Lance Taylor, golan...@googlegroups.com
Sorry to harp on this, but I'm still troubled.

I can see how it could cause confusion, but only if a person is already confused about how array values are passed in general. It's not really true AFAICS that the reflect package restates the language rules since all values reflected in reflect.Values must have a real address and are therefore addressable (this is presumably why there is a value.flagAddr - to be able to make this distinction).

Now, I can see that if you get a reflect.Value of an array, any changes you make to the reflect.Value array will not result in changes to the original array, but that is the same as passing an array to any function.

This issue came up for when I was looking at getting a byte slice from a {[]B,addressable [n]B,[n]B} where B is reflect.Kind uint8. In the first two cases this is easy, call .Bytes(), or .Slice().Bytes(), but the last is not possible without .Indexing across the array - which will be slower. Here there is no issue with changes not being reflected in the original array - that's not the goal (I guess I could use unsafe to get the address from the interface data and then construct a slice, but I'm not sure what the pointer value in an interface holding an array actuall points to - it seems not to point to the first element of the array as shown in previous posts. Clarification?)

thanks
Dan

On 01/02/2013, at 5:54 AM, "Ian Lance Taylor" <ia...@google.com> wrote:

Dan Kortschak

unread,
Feb 2, 2013, 6:33:39 PM2/2/13
to Ian Lance Taylor, golan...@googlegroups.com
I can be pretty dim sometimes.

Yes, the pointer points to a copy of the array.

The rest of the previous email still stands.

Dan
Reply all
Reply to author
Forward
0 new messages