Mathieu Nls
Mathieu Nls

Reputation: 2365

reflect.New returns <nil> instead of initialized struct

I am using reflection for a library I'm building but there's something I don't understand about reflect.New.

type A struct {
    A int
    B string
}

func main() {

    real := new(A)
    reflected := reflect.New(reflect.TypeOf(real)).Elem().Interface()
    fmt.Println(real)
    fmt.Println(reflected)
}

Gives:

$ go run *go
&{0 }
<nil>

Isn't reflect.New supposed to return &{0 } too? (Runnable Version)

Ultimately, I wish to be able to iterate over the fields of the reflected struct (reflected.NumField() gives reflected.NumField undefined (type interface {} is interface with no methods)) and use SetInt, SetString and so on.

Thanks,

Upvotes: 2

Views: 1558

Answers (1)

icza
icza

Reputation: 418227

You used the builtin new() function when you created your real variable, which returns a pointer! Type of real is *A, not A! This is the source of the confusion.

reflect.New() returns a pointer to the (zeroed) value of the given type (wrapped in a reflect.Value). If you pass the type A, you get back a wrapped *A, A initialized / zeroed. If you pass the type *A, you get back a wrapped **A, *A initialized (zeroed), and the zero value for any pointer type is nil.

You basically ask reflect.New() to create a new value of a pointer type (*A), and –as mentioned– its zero value is nil.

You have to pass the type A (and not the type *A). It works like this (try it on the Go Playground):

real := new(A)
reflected := reflect.New(reflect.TypeOf(real).Elem()).Elem().Interface()
fmt.Println(real)
fmt.Println(reflected)

Or like this (Go Playground):

real := A{}
reflected := reflect.New(reflect.TypeOf(real)).Elem().Interface()
fmt.Println(real)
fmt.Println(reflected)

Upvotes: 7

Related Questions