Я использую сторонний пакет, который позволяет создавать структуры определенного неэкспортируемого типа с помощью экспортируемой функции.
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
}
}
Есть ли другой способ добиться того же результата?
@mkopriva Пока нет. Я новичок в этом языке и до сих пор им не пользовался.
Вы можете использовать отражение, чтобы сравнить тип значений с типом 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)
Этот метод по-прежнему требует доступа к неэкспортированному типу. Обратите внимание, что тип OP, с которым нужно сравнивать, — это expr
, а не Expr
.
Это можно было бы сделать немного более неуклюже, используя reflect.TypeOf(v).Name() == "expr"
.
@Adrian Мое решение не относится к неэкспортированному типу, оно использует возвращаемое значение экспортированной функции squirrel.Expr()
, которое является допустимым. Мы могли бы использовать отражение, чтобы «извлечь» возвращаемый тип Expr()
, если его вызов невозможен, но в данном случае это не так. Использование Type.Name()
имеет больше недостатков, чем простота, которую оно обеспечивает.
Вы пробовали отражение?