为了账号安全,请及时绑定邮箱和手机立即绑定

如何通过 reflect.Append 将 nil 附加到动态类型切片

如何通过 reflect.Append 将 nil 附加到动态类型切片

Go
繁星coding 2023-06-19 17:47:32
reflect.Value下面的代码将在追加时引发运行时错误nil:package mainimport (    "fmt"    "reflect")func main() {    var list []interface{}    v := reflect.ValueOf(list)    v = reflect.Append(v, reflect.ValueOf(1))   // [1]    v = reflect.Append(v, reflect.ValueOf("1")) // [1, 1]    v = reflect.Append(v, reflect.ValueOf(nil)) // runtime error    fmt.Println(v)}所以为什么会出现运行时错误?我怎样才能使用reflect.Append添加nil到interface{}切片?
查看完整描述

1 回答

?
缥缈止盈

TA贡献2041条经验 获得超4个赞

interface{}是一种接口类型,它们很“棘手”。它们是具体值和具体类型的包装器,示意性地是(值,类型)对。

因此,当您将具体值传递给需要值的函数时interface{},具体值将interface{}自动隐式地包装在一个值中。如果将 a 传递nil给这样的函数,则接口值本身将为nil. 如果你传递一个nil指向它的指针,比如(*int)(nil),接口值将不会是nil一个持有“(nil, *int)”的接口值。

如果传递nilreflect.ValueOf(),它会产生一个“零” reflect.Value,表示根本没有值。如果将其传递给reflect.Append(),它将没有类型信息,也不知道要将什么附加到切片中。

可以创建表示nil接口值的值。

为此,我们可以从接口指针值的类型描述符开始(指向接口的指针很少有意义,但这就是其中之一)。我们导航到指向类型的类型描述符,即interface{}. 我们获得此类型的零值(使用reflect.Zero()),即nil(接口类型的零值是nil)。

零返回一个值,表示指定类型的零值。结果与 Value 结构的零值不同,后者表示根本没有值。

所以这就是它的样子:

typeOfEmptyIface := reflect.TypeOf((*interface{})(nil)).Elem()

valueOfZeroEmptyIface := reflect.Zero(typeOfEmptyIface)

v = reflect.Append(v, valueOfZeroEmptyIface)

或者作为单行:


v = reflect.Append(v, reflect.Zero(reflect.TypeOf((*interface{})(nil)).Elem()))

要检查结果,让我们使用:


fmt.Printf("%#v\n", v)

并且让我们对切片进行类型断言,并nil使用内置append()函数添加一个值:


list = v.Interface().([]interface{})

list = append(list, nil)

fmt.Printf("%#v\n", list)

让我们做一个明确的额外检查元素是否是nil(将它们与 进行比较nil)。尽管使用%#v动词 this 是多余的,但%v喜欢打印nil持有nil具体值的非接口 as nil(就像接口值本身一样nil)。


fmt.Println(list[2] == nil, list[3] == nil)

输出将是(在Go Playground上尝试):


[]interface {}{1, "1", interface {}(nil)}

[]interface {}{1, "1", interface {}(nil), interface {}(nil)}

true true



查看完整回答
反对 回复 2023-06-19
  • 1 回答
  • 0 关注
  • 96 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信