В чем разница между v. Type().Элем() & В. Элем().Тип ()?

в следующем коде оба параметра, похоже, выделяют один и тот же ресурс

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

Если в этом конкретном примере нет разницы, пример, иллюстрирующий разницу, будет отличным. Также, что является предпочтительным вариантом в этом конкретном случае при попытке выделить для интерфейса.

Edit: reflect.DeepEqual (s0, s1) возвращает false. Я думаю, РВ.Elem ().Type () имеет проблему с нулевыми значениями, поэтому, возможно, rv.Тип.)(Предпочтительнее Elem ().

площадка

1 ответов


нет никакой разницы, если v - это не-nil тип указателя.

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

вот несколько примеров, где rv.Type().Elem() и rv.Elem().Type()) иначе:

// 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, затем проверка nil может быть удалена, и функция будет работать со значениями указателя nil.

вызов reflect.DeepEqual(s0, s1) возвращает false, потому что ptr поля в значениях разные. 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"

как вы можете видеть, размышлять.Все сравнения значений являются ложными, даже если они созданы с использованием одной и той же последовательности вызовов.