doc for reflect Value.Kind() seems incorrect

148 views
Skip to first unread message

Kaviraj Kanagaraj

unread,
Dec 4, 2016, 3:01:20 PM12/4/16
to golang-nuts

 doc for Value.Kind() says,

"If v is the zero Value (IsValid returns false), Kind returns Invalid."

but thats not true. I does return "Invalid" in case of interfaces. but not for every type. It doesn't return "invalid" even if IsValid return false.



Jan Mercl

unread,
Dec 4, 2016, 3:09:55 PM12/4/16
to Kaviraj Kanagaraj, golang-nuts



On Sun, Dec 4, 2016 at 9:01 PM Kaviraj Kanagaraj <kavirajk...@gmail.com> wrote:

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

See https://play.golang.org/p/RoIAXsxhIF


--

-j

Kaviraj Kanagaraj

unread,
Dec 5, 2016, 12:55:13 AM12/5/16
to golang-nuts, kavirajk...@gmail.com
Sry for the typo. Its true that Kind() returns "Invalid" if IsValid returns False. But still docs seems to be misleading. It says "If v is the zero Value (IsValid returns false), Kind returns Invalid."

according to doc, all the variables in the code supposed to have a kind of "Invalid" (since all the variables have zero value) in here https://play.golang.org/p/RoIAXsxhIF


Jan Mercl

unread,
Dec 5, 2016, 1:16:43 AM12/5/16
to Kaviraj Kanagaraj, golang-nuts

On Mon, Dec 5, 2016 at 6:55 AM Kaviraj Kanagaraj <kavirajk...@gmail.com> wrote:

> But still docs seems to be misleading. It says "If v is the zero Value (IsValid returns false), Kind returns Invalid."

--

-j

Axel Wagner

unread,
Dec 5, 2016, 2:21:41 AM12/5/16
to Kaviraj Kanagaraj, golang-nuts
You need to distinguish between "the zero value of it's type" and "the zero (reflect.)Value". The docs here mean the latter, not the former.
What is happening is, that in case of a nil-interface (w and in), the interface gets passed "as is" into reflect.ValueOf, which takes an interface{}. That is, as those are already interfaces, they don't get wrapped, but you just pass the interface header as is. And as they are nil, the interface header has two zero fields, there is no type or dynamic value that reflect could give you a handler for, so reflect.ValueOf gives you an invalid reflect.Value. For the other values, though, there *is* a dynamic value to be packed into the interface{}. Even though they might have the zero value of their type, they do come with a type. So when you pass it to reflect.ValueOf, an interface-header is constructed with a type-field pointing to the respective generated type-info and the value field pointing to a zero value of that type (or, in the case of *int, just set to that pointer, namely nil).

You can remove the distinction between passing interfaces and passing concrete types, by passing a pointer to reflect.ValueOf and using Value.Elem() to get to the value: https://play.golang.org/p/uaNi4mHDmV
Now, you always pass a concrete type (in the case of w, for example, it's *io.Writer) which gets packed into the interface{} and passed to reflect.ValueOf. Elem() then unpacks that interface{} and follows the pointer. In the case of w, unwrapping will give you a pointer to that io.Writer interface value (not the non-existent thing packed in it) and following will give you a nil io.Writer. A nil io.Writer is still a valid reflect.Value, with the type io.Writer.

So, there are three take-aways:
* Kind() is invalid only on the zero-value of a reflect.Value, not on the reflect.Value representing the zero Value of any type. I.e. it's invalid only if you give reflect something without a dynamic type (such as a nil interface)
* Interfaces are purely static types, so if you pass an interface as a different interface, the static information of what methods are on that interface gets erased. If you want to preserve this type information, you need to pass a non-interface type (such as a pointer to an interface).
* Usage of reflect is subtle and difficult. Most gophers shouldn't use it for that reason alone.


On Mon, Dec 5, 2016 at 6:55 AM, Kaviraj Kanagaraj <kavirajk...@gmail.com> wrote:
Sry for the typo. Its true that Kind() returns "Invalid" if IsValid returns False. But still docs seems to be misleading. It says "If v is the zero Value (IsValid returns false), Kind returns Invalid."

according to doc, all the variables in the code supposed to have a kind of "Invalid" (since all the variables have zero value) in here https://play.golang.org/p/RoIAXsxhIF


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Kaviraj Kanagaraj

unread,
Dec 6, 2016, 1:44:54 AM12/6/16
to golang-nuts, kavirajk...@gmail.com
Thanks Axel for the detail explanation. Make sense now. :)
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages