Reputation: 5126
Code written around something like this is causing an issue:
func CreateNewItemOfType(returnType reflect.Type) (interface {}) {
return reflect.New(returnType).Interface();
}
... How can one actually return a struct of returnType
and not a pointer to a struct, as reflect
creates here? The compiler builds this fine but panics at run-time, yet will not accept an asterisk in front of the return call here in order to actually return the struct and not a pointer.
Upvotes: 1
Views: 54
Reputation: 418227
reflect.New()
creates a new value of the specified type, and returns the reflect.Value
descriptor of a pointer to that value. You may use Value.Elem()
to "navigate" from pointer to pointed value wrapped in a reflect.Value
. Then you can call Value.Interface()
to get the value (struct) as an interface{}
value.
If you need a value of concrete type, you may use type assertion to "extract" the value wrapped in the interface{}
value.
func CreateNewItemOfType(returnType reflect.Type) interface{} {
return reflect.New(returnType).Elem().Interface()
}
Testing it:
type Point struct {
X, Y int
}
t := reflect.TypeOf(Point{})
i := CreateNewItemOfType(t) // i is of type interface{}
fmt.Printf("%T %+v\n", i, i)
pt := i.(Point) // pt is of type Point
fmt.Printf("%T %+v\n", pt, pt)
Output (try it on the Go Playground):
main.Point {X:0 Y:0}
main.Point {X:0 Y:0}
Note:
It is also possible to obtain the non-pointer struct value if Value.Elem()
is not used. For that, you need to type-assert the pointer value (of type *Point
), then you can dereference the pointer to get the non-pointer.
See this example:
t := reflect.TypeOf(Point{})
pi := reflect.New(t).Interface() // pi is of type interface{}
fmt.Printf("%T %+v\n", pi, pi)
ppt := pi.(*Point) // pt is of type *Point
fmt.Printf("%T %+v\n", ppt, ppt)
i2 := *ppt // i2 is of type Point
fmt.Printf("%T %+v\n", i2, i2)
Output:
*main.Point &{X:0 Y:0}
*main.Point &{X:0 Y:0}
main.Point {X:0 Y:0}
Upvotes: 3