Введите assert пользовательский тип в базовый тип - PullRequest
1 голос
/ 25 июня 2019

Можно ли ввести assert пользовательский тип в его базовый тип?

Например, если у меня есть следующее

type A []interface{}

var x = map[string]interface{}{
        "hello":"a",
        "world":A{"b","c"},
    }

y := x["world"]

Тогда, если я попытаюсь ввести assert через y.([]interface{}) Я получаю сообщение об ошибке //interface {} is A, not []interface {}.

Редактировать: Как отмечается в ответе ниже, я могу утверждать, чтобы ввести A через y.(A).Проблема связана с тем, что x предоставляется драйвером Mongo.Некоторые драйверы реализуют свои собственные типы, например, официальный драйвер Монго реализует тип bson.A для типов []interface.Если я переключаю драйверы, мои утверждения типа должны быть изменены, чтобы соответствовать их пользовательским типам, чего я хочу избежать.

Ответы [ 2 ]

3 голосов
/ 25 июня 2019

Когда вводит тип (to) конкретного типа, вы можете вводить только тот тип, который хранится в значении интерфейса, но не его базовый тип.Конечно, когда у вас есть конкретный тип, вы можете преобразовать в базовый тип.

Вы сказали, что хотите избежать этого, вы хотите избежать обращения к конкретному типу.

Для этого вам понадобится рефлексия.Получите дескриптор значения reflect.Value и используйте метод Value.Convert() для "прямого" преобразования в его базовый тип, пропуская "фактический" тип.Это будет успешно, потому что значение может быть преобразовано в значение его базового типа.

Конечно, метод Value.Convert() даст значение типа reflect.Value (а не []interface{}), но вы можетеполучите значение interface{}, заключив это в Value.Interface().Теперь у вас будет interface{}, заключающий в себе конкретное значение типа []interface{}, из которого вы теперь можете набрать assert значение типа []interface{}.

См. Этот пример:

z := reflect.ValueOf(y).Convert(reflect.TypeOf([]interface{}{})).
    Interface().([]interface{})

fmt.Printf("%T %v", z, z)

Вывод (попробуйте на Go Playground ):

[]interface {} [b c]

Здесь много шаблонов, и это будет не так эффективно, как простое утверждение типаи преобразование.Старайтесь не делать это таким образом.

1 голос
/ 25 июня 2019

Вы не можете набрать assert переменную y до []interface{}, поскольку фактический тип данных y равен A (даже если A является псевдонимом []interface{}).

Рабочий пример:

fmt.Println(y.(A))

Но вы можете преобразовать переменную с типом данных A в []interface{}, используя преобразование .Пример:

w := y.(A)
x := []interface{}(w)

// or 

z := []interface{}(y.(A))
...