What is the difference between v.Type (). Elem () & v. Elem (). A type()?

In the following code, both options allocate the same resource

func Allocate(v interface{}) error { rv := reflect.ValueOf(v) if rv.IsNil() { return errors.New("Value of v is nil") } s0 := reflect.New(rv.Type().Elem()) s1 := reflect.New(rv.Elem().Type()) return errors.New(fmt.Sprintf("What the diff? %v %v", s0, s1)) } 

If there is no difference in this particular example, the example illustrating the difference will be large. Also, what is the preferred option in this particular case when trying to allocate for an interface.

Edit: reflect.DeepEqual (s0, s1) returns false. I think rv.Elem (). Type () has a problem with null values, so maybe rv.Type (). Elem () is preferred.

Playground

+6
source share
1 answer

It makes no difference if v is a non-nil pointer type.

 s := "hello" rv := reflect.ValueOf(&s) fmt.Println(rv.Type().Elem() == rv.Elem().Type()) // prints "true" 

Here are some examples where rv.Type().Elem() and rv.Elem().Type()) different:

 // nil pointer var p *string rv := reflect.ValueOf(p) fmt.Println(rv.Type().Elem()) // prints "string" fmt.Println(rv.Elem().Type()) // panic: call of reflect.Value.Type on zero Value // interface value var i interface{} = "hello" rv := reflect.ValueOf(&i).Elem() fmt.Println(rv.Type()) // prints "interface {}" fmt.Println(rv.Elem().Type()) // prints "string" fmt.Println(rv.Type().Elem()) // panic: Elem of invalid type 

If rv.Type().Elem() used in Allocate , then the nil check can be removed, and the function will work with the nil pointer values.

Calling reflect.DeepEqual(s0, s1) returns false because the ptr values ​​in the values ​​are different. DeepEqual compares unsafe pointers as simple values, not as pointers. This example may help explain what happens:

 v := "hello" rv := reflect.ValueOf(&v) s0 := reflect.New(rv.Type().Elem()) s1 := reflect.New(rv.Elem().Type()) s2 := reflect.New(rv.Type().Elem()) s3 := reflect.New(rv.Elem().Type()) fmt.Println(reflect.DeepEqual(s0, s1)) // prints "false" fmt.Println(reflect.DeepEqual(s0, s2)) // prints "false" fmt.Println(reflect.DeepEqual(s1, s3)) // prints "false" fmt.Println(reflect.DeepEqual(s2, s3)) // prints "false" fmt.Println(reflect.DeepEqual(s0.Interface(), s1.Interface())) // prints "true" fmt.Println(reflect.DeepEqual(s0.Interface(), s2.Interface())) // prints "true" fmt.Println(reflect.DeepEqual(s1.Interface(), s3.Interface())) // prints "true" fmt.Println(reflect.DeepEqual(s2.Interface(), s3.Interface())) // prints "true" 

As you can see, reflect.Value comparisons are false, even if they were created using the same call sequence.

+6
source

All Articles