非导出类型的类型声明

时间:2019-04-10 08:54:59

标签: go types

我正在使用第三方软件包,该软件包允许您通过导出的函数创建某些非导出类型的结构。

package squirrel

type expr struct {
    sql string
    args []interface{}
}

func Expr(sql string, args ...interface{}) expr {
    return expr{sql: sql, args: args}
}

由于该库的其他功能接收数据的方式,我最终得到了这样的一张图:

m := map[string]interface{} {
    "col1": 123,
    "col2": "a_string",
    "col3": Expr("now()"),
}

但是由于该库中的功能不同,我需要从该地图中过滤掉所有squirrel.expr

很明显,这样做无法直接声明类型:

filtered := make(map[string]interface{})
for k, v := range m {
    switch v.(type) {
    case squirrel.expr:
        continue
    default:
        filtered[k] = v
    }
}

还有另一种方法可以达到相同的结果吗?

1 个答案:

答案 0 :(得分:5)

您可以使用反射将值的类型与squirrel.expr的类型进行比较。这里的类型表示reflect.Type获取的reflect.TypeOf()描述符。

例如:

m := map[string]interface{}{
    "col1": 123,
    "col2": "a_string",
    "col3": squirrel.Expr("now()"),
}
fmt.Println(m)

exprType := reflect.TypeOf(squirrel.Expr(""))

filtered := make(map[string]interface{})
for k, v := range m {
    if reflect.TypeOf(v) == exprType {
        continue
    }
    filtered[k] = v
}
fmt.Println(filtered)

这将输出:

map[col1:123 col2:a_string col3:{now() []}]
map[col1:123 col2:a_string]

注意:

我们通过传递reflect.Type调用的返回值(类型为squirrel.Expr())来获取要过滤掉的值的squirrel.expr描述符。在这种情况下这很好,但是如果仅为了获取类型而调用此函数是不可行的(例如,该调用具有必须避免的副作用),我们可以避免这种情况。我们可以使用反射来获取reflect.Type函数本身的squirrel.Expr描述符,并获取其返回类型的类型描述符。这是可以做到的:

exprType := reflect.TypeOf(squirrel.Expr).Out(0)