gpt4 book ai didi

go - v.Type().Elem() 和 v.Elem().Type() 有什么区别?

转载 作者:IT王子 更新时间:2023-10-29 01:18:58 25 4
gpt4 key购买 nike

在下面的代码中,两个选项似乎都分配了相同的资源

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

如果这个具体示例没有区别,那么说明区别的示例会很棒。此外,在尝试为接口(interface)分配时,在这种特定情况下,更可取的选项是什么。

编辑:reflect.DeepEqual(s0, s1) 返回 false。我认为 rv.Elem().Type() 在处理零值时存在问题,因此 rv.Type().Elem() 可能是首选。

Playground

最佳答案

如果 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

如果在 Allocate 中使用了 rv.Type().Elem(),那么可以移除 nil 检查并且该函数将使用 nil 指针值。

调用 reflect.DeepEqual(s0, s1) 返回 false 因为 ptr fields在值(value)观上是不同的。 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 比较都是错误的,即使是使用相同的调用序列创建的。

关于go - v.Type().Elem() 和 v.Elem().Type() 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39019040/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com