非导出类型的类型声明

Jak*_*kub 1 types go

我正在使用第3方程序包,该程序包允许您通过导出功能创建某些非导出类型的结构。

package squirrel

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

func Expr(sql string, args ...interface{}) expr {
    return expr{sql: sql, args: args}
}
Run Code Online (Sandbox Code Playgroud)

由于该库的其他功能接受数据的方式,我最终得到了这样的映射:

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

但是由于该库中的函数不同,我需要squirrel.expr从该地图中过滤掉所有内容。

显然,我无法通过以下方式直接声明类型:

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

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

icz*_*cza 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)
Run Code Online (Sandbox Code Playgroud)

这将输出:

map[col1:123 col2:a_string col3:{now() []}]
map[col1:123 col2:a_string]
Run Code Online (Sandbox Code Playgroud)

注意:

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

exprType := reflect.TypeOf(squirrel.Expr).Out(0)
Run Code Online (Sandbox Code Playgroud)

  • @Adrian我的解决方案没有引用未导出的类型,它使用了已导出的`squirrel.Expr()`函数的返回值,该值是有效的。如果调用不可行,可以使用反射来“提取” Expr()的返回类型,但是在这种情况下不是这样。使用Type.Name()具有比它提供的简便性更多的缺点。 (2认同)