我可以使用typedef进行类型断言吗?

我有一个自定义类型,可以让我更方便地使用 API:

type Object map[string]interface{}

这件事不起作用:

var mockResponse = map[string]interface{}{"success": true}
resp, ok := mockResponse.(Object)
// ok = false

我可以做任何事情,这样mockResponse.(Object)oktrue?基本上都是一样的类型。。。

回答

首先,您的“伪代码”是编译时错误。您不能对具有具体类型的值使用类型断言(没有意义,具体类型是具体类型,没有别的),您只能在接口值上使用它。

例子应该是:

var mockResponse interface{} = map[string]interface{}{"success": true}
resp, ok := mockResponse.(Object)

请注意,如果mockResponse是 type map[string]interface{},则不需要类型断言,您可以简单地将其转换为Object

var mockResponse = map[string]interface{}{"success": true}
obj := Object(mockResponse)

该类型定义创建了一个新的,独特的类型。并且仅当您使用相同的具体类型时,对具体类型的类型断言才成立。

您可以做的是编写一个Object从接口值中提取的辅助函数,该函数可以处理这两种情况map[string]interface{},也可以处理具体类型Object

func getObj(x interface{}) (o Object, ok bool) {
    switch v := x.(type) {
    case Object:
        return v, true
    case map[string]interface{}:
        return Object(v), true
    }
    return nil, false
}

测试它:

resp, ok := getObj(map[string]interface{}{"success": true})
fmt.Println(resp, ok)

resp, ok = getObj(Object{"success": true})
fmt.Println(resp, ok)

resp, ok = getObj("invalid")
fmt.Println(resp, ok)

输出(在Go Playground上试试):

map[success:true] true
map[success:true] true
map[] false

注意:上面getObj()没有处理可以Object从接口值“获取” an 的所有可能情况。

例如,如果我们有这样的类型定义:

type Object2 Object

Passing a value of Object2 to getObj(), an Object would not be extracted from it, even though a value of type Object2 could be converted to Object:

resp, ok = getObj(Object2{"success": true})
fmt.Println(resp, ok) // map[] false

If you want to handle all possible cases where the concrete value is convertible to Object, you may use reflection:

var objType = reflect.TypeOf(Object{})

func getObj(x interface{}) (o Object, ok bool) {
    if v := reflect.ValueOf(x); v.Type().ConvertibleTo(objType) {
        o, ok = v.Convert(objType).Interface().(Object)
        return
    }
    return nil, false
}

Testing it (try this one on the Go Playground):

resp, ok = getObj(Object2{"success": true})
fmt.Println(resp, ok) // map[success:true] true

Using reflection is slower than a simple type assertion or type switch, so you can mix the 2 solutions:

func getObj(x interface{}) (o Object, ok bool) {
    // First try the trivial cases:
    switch v := x.(type) {
    case Object:
        return v, true
    case map[string]interface{}:
        return Object(v), true
    }

    // Then revert to reflection:
    if v := reflect.ValueOf(x); v.Type().ConvertibleTo(objType) {
        o, ok = v.Convert(objType).Interface().(Object)
        return
    }
    return nil, false
}


以上是我可以使用typedef进行类型断言吗?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>