reflect: set to nil?

1,307 views
Skip to first unread message

stephanos

unread,
Oct 13, 2013, 5:05:43 AM10/13/13
to golan...@googlegroups.com
Hi there,

I'm stuck on this reflection problem: I have an interface{} and want to set it's value to 'nil'.
You can find the issue reduced to a few lines of code here: http://play.golang.org/p/6F7Rp9QqE9

It's probably super-simple but I just don't get it.

Regards
Stephan

Rémy Oudompheng

unread,
Oct 13, 2013, 5:13:04 AM10/13/13
to stephanos, golang-nuts
2013/10/13 stephanos <stephan...@gmail.com>:
v.Set(reflect.Zero(v.Type())

Rémy.

stephanos

unread,
Oct 13, 2013, 5:22:10 AM10/13/13
to golan...@googlegroups.com, stephanos
Hm, when I apply that line the result is not nil: http://play.golang.org/p/WtC34_rhgK

Does it have something to do with the .Elem()? What's the reverse, .Addr()?

Jsor

unread,
Oct 13, 2013, 5:33:28 AM10/13/13
to golan...@googlegroups.com, stephanos
Check reflect.ValueOf(src).Type(), it will say that the type of src is MyStruct. A struct can't be set to nil, only to its zero type.

ValueOf has no way to know the type the caller assigned to the argument when ValueOf was called, because all arguments to ValueOf are interface{}, that information is lost in the calling. Thus, as far as reflect is concerned, you're trying to do this:

var src MyStruct
src = nil // This isn't allowed

There are ways to set MyWrapper.src to nil, though I'm not sure you can do it without using reflect on a pointer to an instance of MyWrapper. I'll play around and see what I can come up with.

stephanos

unread,
Oct 13, 2013, 5:38:17 AM10/13/13
to golan...@googlegroups.com, stephanos
Thanks for your detailed message!

I mean when I call reflect.ValueOf(src) I get the pointer to the struct, don't I? I just use it to call Elem() and 'ignore' it. 
Would it help if I store it in the wrapper as well?

Jsor

unread,
Oct 13, 2013, 5:44:43 AM10/13/13
to golan...@googlegroups.com, stephanos
Nevermind, you're right, it's Elem that's causing the problem. Otherwise you get a * to myStruct, trying to set it gets you an Unaddressable Value error. Hmm. I'm still playing around.

Rémy Oudompheng

unread,
Oct 13, 2013, 5:53:17 AM10/13/13
to stephanos, golang-nuts
2013/10/13 stephanos <stephan...@gmail.com>:
> Hm, when I apply that line the result is not nil:
> http://play.golang.org/p/WtC34_rhgK
>
> Does it have something to do with the .Elem()? What's the reverse, .Addr()?
>

If you want self.src to be nil the simplest way is:

self.src = nil

Rémy.

Jsor

unread,
Oct 13, 2013, 6:01:05 AM10/13/13
to golan...@googlegroups.com, stephanos
http://play.golang.org/p/YZQ99H34NE

Your main problem was that you were the address of src (the argument to the constructor) and MyStruct.src were different. By using a pointer to a myStruct.src, and using Elem, I was able to overwrite it with the Zero value of v.Elem() -- which is the Zero of an interface{}, thus nil.

Jsor

unread,
Oct 13, 2013, 6:03:35 AM10/13/13
to golan...@googlegroups.com, stephanos
Wow, my first sentence made no sense. The main problem was just that you were modifying completely different memory locations, basically.

stephanos

unread,
Oct 13, 2013, 6:21:26 AM10/13/13
to golan...@googlegroups.com, stephanos
Thank you Jsor and Rémy. I think I got it now :)

PS: I love the Go community.

stephanos

unread,
Oct 13, 2013, 6:33:39 AM10/13/13
to golan...@googlegroups.com, stephanos
Argh, I think I still don't completely got it :(

I realized that I want the original struct to be nil, not the value in the wrapper.

Jsor

unread,
Oct 13, 2013, 6:42:27 AM10/13/13
to golan...@googlegroups.com, stephanos
Structs can't be nil.

stephanos

unread,
Oct 13, 2013, 6:43:19 AM10/13/13
to golan...@googlegroups.com, stephanos
Sorry, of course I meant the pointer to the struct (s in my example).


On Sunday, October 13, 2013 12:42:27 PM UTC+2, Jsor wrote:
Structs can't be nil.

Rémy Oudompheng

unread,
Oct 13, 2013, 6:50:02 AM10/13/13
to stephanos, golang-nuts
2013/10/13 stephanos <stephan...@gmail.com>:
> Sorry, of course I meant the pointer to the struct (s in my example).
>

Why do you want such a thing? I can't think of a reason why you would need that.

Rémy.

Jsor

unread,
Oct 13, 2013, 6:52:15 AM10/13/13
to golan...@googlegroups.com, stephanos
Your problem is pointers again. You want to modify a variable outside of the scope, so you need a pointer to it.


Note, however, that this WILL NOT, set src to nil. This is getting complex and whatever you're attempting to do, you should probably consider if you really need it. I'm not clear on why you need to wrap a variable in another area of your program and set it to nil.

stephanos

unread,
Oct 13, 2013, 7:02:49 AM10/13/13
to golan...@googlegroups.com, stephanos
I have a data layer that works on top of appengine/datastore. When I do a query instead of fetching the results directly, I just fetch the keys. Then I dynamically generate a slice of structs via reflect.New & reflect.Append and try to do a batch fetch. The whole process allows me to do a cache lookup for each key in order to reduce the size of the batch (thus reducing the cost). It's all working fine.

But one thing that's annoying is the ErrNoSuchEntity. I don't want to drag this along all around my code base. I think it's more idiomatic to return no error but an empty struct pointer. That - to me - represents the situation much better.

So basically the code receives a pointer to a struct and when no entry was found it should set it to nil.

PS: the wrapper analyzes the fields of the structure (e.g. reading tags to identify indexing).

chris dollin

unread,
Oct 13, 2013, 7:09:37 AM10/13/13
to stephanos, golang-nuts
On 13 October 2013 12:02, stephanos <stephan...@gmail.com> wrote:

So basically the code receives a pointer to a struct and when no entry was found it should set it to nil.

Doesn't that mean it should receive a pointer-to-pointer-to-struct?
Then you can use the outer layer of pointer to point to the pointer
that you want to set to nil (or not).

Of course you could return the pointer-to-struct as one of your
results, rather than trying to update some existing pointer.

 Chris

--
Chris "allusive" Dollin

stephanos

unread,
Oct 13, 2013, 8:46:34 AM10/13/13
to golan...@googlegroups.com, stephanos
Thanks Chris and Jsor. The pointer-to-pointer-to-struct construct works great! :)
Reply all
Reply to author
Forward
0 new messages