Go 非导出类型的类型断言

Go 非导出类型的类型断言,go,types,Go,Types,我使用的是第三方软件包,它允许您通过导出函数创建某种非导出类型的结构 打包松鼠 类型expr结构{ sql字符串 args[]接口{} } func Exprsql字符串,args…接口{}expr{ 返回表达式{sql:sql,args:args} } 由于这个库的其他函数接受数据的方式,我最终得到了这样一个映射: m:=map[string]接口{}{ col1:123, col2:一根线, col3:Exprnow, } 但是由于这个库中的函数不同,我需要从这个映射中过滤掉所有squirr

我使用的是第三方软件包,它允许您通过导出函数创建某种非导出类型的结构

打包松鼠 类型expr结构{ sql字符串 args[]接口{} } func Exprsql字符串,args…接口{}expr{ 返回表达式{sql:sql,args:args} } 由于这个库的其他函数接受数据的方式,我最终得到了这样一个映射:

m:=map[string]接口{}{ col1:123, col2:一根线, col3:Exprnow, } 但是由于这个库中的函数不同,我需要从这个映射中过滤掉所有squirrel.expr

显然,我无法通过这样做直接断言类型:

筛选:=makemap[string]接口{} 对于k,v:=范围m{ 开关v型{ case squirrel.expr: 持续 违约: 过滤[k]=v } }
是否有其他方法可以达到相同的结果?

您可以使用反射来比较值的类型和squirrel.expr的类型。这里的类型是指通过获取的描述符

例如:

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]
注:

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

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

您可以使用反射将值的类型与squirrel.expr的类型进行比较。这里的类型是指通过获取的描述符

例如:

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]
注:

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

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

你试过了吗?@mkopriva还没有。我不熟悉这门语言,到目前为止还没有使用过。你试过吗?@mkopriva还没有。我不熟悉这种语言,到目前为止还没有使用过它。这种方法仍然需要访问未报告的类型。请注意,类型OP需要与is expr进行比较,而不是expr。可以使用reflect.TypeOfv.Name==expr进行比较。@Adrian我的解决方案没有引用未报告的类型,它使用导出的squirrel.expr函数的返回值,这是有效的。如果调用Expr不可行,我们可以使用反射来提取Expr的返回类型,但在本例中不是这样。使用Type.Name比它提供的简单性有更多的缺点。此方法仍然需要访问未报告的类型。请注意,类型OP需要与is expr进行比较,而不是expr。可以使用reflect.TypeOfv.Name==expr进行比较。@Adrian我的解决方案没有引用未报告的类型,它使用导出的squirrel.expr函数的返回值,这是有效的。如果调用Expr不可行,我们可以使用反射来提取Expr的返回类型,但在本例中不是这样。使用Type.Name比它提供的简单性有更多的缺点。