Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between v.Type().Elem() & v.Elem().Type()?

Tags:

reflection

go

In the following code, both options seem to 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's the diff? %v %v", s0, s1))
}

If there's no difference in this specific example, an example illustrating the difference will be great. Also what's the preferable option in this specific case when trying to allocate for an interface.

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

Playground

like image 830
Sridhar Avatar asked Aug 18 '16 13:08

Sridhar


People also ask

What is the difference between data element and built in type?

Difference: Data element contains the business and technical information about a field. It contains Data type, length, field labels. Data element can contain a domain within it for type and length information instead of 'built-in type' and we can also associate search help with Data Element.

What is the difference between inline and V-type engines?

There are many mechanical differences, with one clear difference being that inline engines have a crankshaft running from front to back along the bottom center of the engine. In contrast, V engines have a crankshaft that runs from side to side in the upper part of the engine.

What is the difference between Vif and V-show in CSS?

The key difference is that v-if conditionally renders elements and v-show conditionally displays elements. This means that v-if will actually destroy and recreate elements when the conditional is toggled. Meanwhile, v-show will always keep the element in the DOM and will only toggle its display by changing its CSS.

What are the different types of finite elements?

There are different types of finite elements. These are mainly classified based on geometrical dimensions (1D, 2D & 3D), you can further add types based on element order, other or miscellaneous types. Refer Figure 1 for types of elements: In case of 1D elements one of the dimensions is very large compare to other two dimensions.


1 Answers

There is 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()) are 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() is used in Allocate, then the nil check can be removed and the function will work with nil pointer values.

The call reflect.DeepEqual(s0, s1) returns false because the ptr fields in the values are different. DeepEqual compares unsafe pointers as simple values, not as pointers. This example might help explain what's going on:

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, the reflect.Value comparisons are all false, even when created using the same sequence of calls.

like image 113
Bayta Darell Avatar answered Sep 19 '22 02:09

Bayta Darell