2016-08-18 18 views
5

, her iki seçeneğin bu özel örnekte hiçbir fark varsa aynı kaynak yönetmekv.Type() .Elem() ve v.Elem() arasındaki fark nedir. Aşağıdaki kodda

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

tahsis görünüyor, farkı gösteren bir örnek harika olacak. Ayrıca, bir arabirim için ayırmaya çalışırken bu özel durumda tercih edilen seçenek nedir.

Düzeltme: reflect.DeepEqual (s0, s1) false değerini döndürür. Bence rv.Elem(). Type() 'ın sıfır değerleri ile ilgili bir problemi vardır, bu yüzden belki rv.Type() .Elem() tercih edilir. v eğer hiçbir fark yoktur

Playground

+1

Eğer 'v' bir işaretçi türüyse bence yok. – Volker

+0

Ben de öyle düşünmedim ama bazı farklılıklar olmalı çünkü reflect.DeepEqual (s0, s1) false değerini döndürür – Sridhar

cevap

5

olmayan bir sıfır işaretçi türüdür. rv.Type().Elem(), Allocate kullanılan sonra sıfır kontrol çıkarılabilir ve fonksiyon nil işaretçi değerleri ile çalışacak

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

ise:

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

Burada rv.Type().Elem() ve rv.Elem().Type()) farklı olan bazı örnekler verilmiştir. Değerler

reflect.DeepEqual(s0, s1) numaralı çağrı yanlıştır, çünkü değerlerdeki ptr fields farklıdır. DeepEqual, güvenli olmayan işaretçileri, işaretçi olarak değil, basit değerler olarak karşılaştırır.

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" 

Gördüğünüz gibi, reflect.Value karşılaştırmalar bile çağrıların aynı sırayı kullanılarak oluşturulan, tüm yanlıştır: Bu örnek ne olup bittiğini açıklamaya yardımcı olabilir.

+0

Bunun gibi görünüyor. Rv.Elem() .Valid() olduğu sürece, ikisi benzerdir. – Sridhar

+0

Burada neler olduğunu düşünüyorsunuz (https://play.golang.org/p/8HydwIfgP3)? – Sridhar

+0

@Sridhar güncellenmiş cevabı görüntüle –

İlgili konular