【问题标题】:Type assert custom type to base type类型将自定义类型断言为基本类型
【发布时间】:2019-11-06 21:41:14
【问题描述】:

是否可以将自定义类型断言为其基本类型?

例如,如果我有以下情况

type A []interface{}

var x = map[string]interface{}{
        "hello":"a",
        "world":A{"b","c"},
    }

y := x["world"]

然后,如果我尝试通过 y.([]interface{}) 键入 assert,我会收到错误 //interface {} is A, not []interface {}

编辑:正如下面的答案所指出的,我可以通过y.(A) 断言类型 A。问题源于 x 由 Mongo 驱动程序提供。一些驱动实现了自己的类型,例如官方的 mongo 驱动为[]interface 类型实现了一个bson.A 类型。如果我切换驱动程序,那么我的类型断言需要更改以匹配它们的自定义类型,这是我想要避免的。

【问题讨论】:

  • 如果您需要访问特定于动态类型的某些东西,例如结构字段或不属于接口的方法,您只需要断言接口值的类型。如果您依赖于特定于特定驱动程序的某些东西,那么该代码显然无法与另一个驱动程序一起使用。那就不要那样做。仅依赖于与您想要支持的所有驱动程序一起使用的一些通用接口。

标签: go types type-conversion type-assertion


【解决方案1】:

type asserting (to) 一个具体类型时,你只能键入assert 存储在接口值中的相同类型,而不是它的基类型。当然,当您拥有具体类型时,您可以将其convert 设置为它的基本类型。

你说你想避免这种情况,你想避免不得不引用具体类型。

为此,您需要反思。获取该值的reflect.Value 描述符,并使用Value.Convert() 方法“直接”转换为其基类型,跳过“实际”类型。这会成功,因为可以将值转换为其基类型的值。

当然,Value.Convert() 方法会产生一个reflect.Value 类型的值(而不是[]interface{}),但是您可以使用Value.Interface() 获得包装它的interface{} 值。现在,您将拥有一个 interface{},它包装了 []interface{} 类型的具体值,您现在可以从中键入断言 []interface{} 类型的值。

看这个例子:

z := reflect.ValueOf(y).Convert(reflect.TypeOf([]interface{}{})).
    Interface().([]interface{})

fmt.Printf("%T %v", z, z)

输出(在Go Playground 上试试):

[]interface {} [b c]

这里有很多样板,这不会像简单的类型断言和转换那样有效。尽量避免这样做。

【讨论】:

    【解决方案2】:

    您不能将type assert 变量y 转换为[]interface{},因为y 的实际数据类型是A(即使A[]interface{} 的别名)。

    工作示例:

    fmt.Println(y.(A))
    

    但是您可以使用conversion 将具有A 数据类型的变量转换为[]interface{}。示例:

    w := y.(A)
    x := []interface{}(w)
    
    // or 
    
    z := []interface{}(y.(A))
    

    【讨论】:

    • A 不是 aliasinterface{}
    猜你喜欢
    • 1970-01-01
    • 2014-01-12
    • 2020-10-22
    • 2022-01-22
    • 2021-04-24
    • 1970-01-01
    • 2018-11-19
    • 2021-03-26
    • 1970-01-01
    相关资源
    最近更新 更多