2

Using the Go reflect package I'd like to get a nil pointer of a particular type, for example I'd like a reflect.Value that represents *int with a value of nil not *0

I'm currently getting the zeroed value like this but this is *0 not nil

// varType is a reflect.Type
reflect.New(reflect.PtrTo(varType).Elem())

Will give me a zero value, e.g. *0 for *int

But what I can't quite workout is now to get a reflect.Value of say type *int and it be nil not *0

I understand why .Set(reflect.ValueOf(nil)) does not work. Perhaps I've missed a crucial step?

icza
  • 389,944
  • 63
  • 907
  • 827
rhys_stubbs
  • 538
  • 6
  • 16

1 Answers1

2

Use reflect.Zero() instead of reflect.New(). reflect.New() allocates a value of the given type, and returns a pointer to it (wrapped in reflect.Value).

reflect.Zero() does not allocate a new value, it returns the zero value of the given type (wrapped in reflect.Value). So if you pass the reflect.Type descriptor of *int, or any other pointer type, since the zero value for pointer types is nil, you get back a nil pointer.

For example:

var i int
varType := reflect.TypeOf(i)
v := reflect.Zero(reflect.PtrTo(varType)).Interface()
fmt.Printf("Type: %T, Value: %v\n", v, v)

if p, ok := v.(*int); ok {
    fmt.Println("v holds *int, its value is:", p)
}

Output (try it on the Go Playground):

Type: *int, Value: <nil>
v holds *int, its value is: <nil>

Do note however that you have to call Value.Interface() to get a value out of reflect.Value (to leave the reflection world). Also note that this returned interface value (it has type interface{} or any) will not be nil, but it packs a *int type and a nil pointer value. For details, see Hiding nil values, understanding why Go fails here

icza
  • 389,944
  • 63
  • 907
  • 827
  • thanks, I actually had `reflect.Zero(reflect.PointerTo(varType))` but I think I'd been overthinking/confusing myself as this does exactly what I wanted/expected. Thanks for the detailed answer! – rhys_stubbs Mar 27 '23 at 14:10