2016-08-18 9 views
5

निम्न कोड में, दोनों विकल्पों में एक ही संसाधन आवंटित करने के लिएv.Type()। Elem() और v.Elem() के बीच क्या अंतर है। टाइप()?

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)) 
} 

यदि इस विशिष्ट उदाहरण में कोई अंतर नहीं लगता है, एक उदाहरण के अंतर को दर्शाता हुआ बहुत अच्छा होगा। इंटरफ़ेस के लिए आवंटित करने का प्रयास करते समय भी इस विशिष्ट मामले में बेहतर विकल्प क्या है।

संपादित करें: प्रतिबिंबित करें। डीपईक्वल (एस 0, एस 1) झूठी रिटर्न देता है। मुझे लगता है कि rv.Elem() टाइप() में शून्य मानों से निपटने में कोई समस्या है, इसलिए शायद rv.Type()। Elem() को प्राथमिकता दी जाती है।

Playground

+1

मुझे लगता है कि अगर कोई नहीं है तो 'v' एक सूचक प्रकार है। – Volker

+0

मैंने ऐसा नहीं सोचा था, लेकिन कुछ अंतर होना चाहिए क्योंकि प्रतिबिंबित करें। डीपईक्वल (एस 0, एस 1) झूठी रिटर्न – Sridhar

उत्तर

5

वहाँ अगर v कोई अंतर नहीं है एक गैर शून्य सूचक प्रकार है।

// 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 

तो rv.Type().Elem(), Allocate में प्रयोग किया जाता है तो शून्य जांच हटाया जा सकता है और समारोह शून्य सूचक मान के साथ काम करेंगे:

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

यहाँ कुछ उदाहरण हैं जहां rv.Type().Elem() और rv.Elem().Type()) अलग कर रहे हैं।

कॉल reflect.DeepEqual(s0, s1) गलत लौटाता है क्योंकि मानों में ptr fields भिन्न हैं। DeepEqual असुरक्षित पॉइंटर्स की तुलना सरल मानों के रूप में करता है, पॉइंटर्स के रूप में नहीं।

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" 

आप देख सकते हैं, reflect.Value तुलना सब झूठे हैं, यहां तक ​​कि कॉल की उसी क्रम का उपयोग करते समय बनाया: इस उदाहरण समझाने क्या हो रहा है मदद कर सकता है।

+0

ऐसा लगता है। जब तक rv.Elem()। IsValid(), दोनों समान हैं। – Sridhar

+0

आपको क्या लगता है [यहां] (https://play.golang.org/p/8HydwIfgP3) पर जा रहा है? – Sridhar

+0

@ श्रीधर अपडेट किए गए उत्तर को देखें –

संबंधित मुद्दे