Ответ 1
TL;DR
Для утверждений типа (которые вы используете) имеет значение только фактический тип. Таким образом, somethingFuncy
равен только somethingFuncy
, а не func(int) bool
.
Объяснение
Для начала это не имеет никакого отношения к кастингу. В игре нет кастинга. Существуют типы утверждений и типы конверсий.
Вы имеете дело с утверждением типа и считаете, что выполняются те же условия как для типов конверсий. Я сделал ту же ошибку, читая ваш вопрос, но на самом деле существует огромная разница в поведении.
Предположим, что у вас есть два типа, скажем int
и type MyInt int
. Они являются конвертируемыми, поскольку они оба
использовать один и тот же базовый тип (одно из правил преобразования), поэтому это работает (play):
var a int = 10
var b MyInt = MyInt(a)
Теперь предположим, что a
не имеет тип int
, а типа interface{}
(play):
var a interface{} = int(10)
var b MyInt = MyInt(a)
Компилятор скажет вам:
не может преобразовать (type interface {}), чтобы ввести MyInt: require type assertion
Итак, теперь мы больше не делаем конверсии, а утверждения. Мы должны это сделать (play):
var a interface{} = int(10)
var b MyInt = a.(MyInt)
Теперь у нас та же проблема, что и в вашем вопросе. Это утверждение терпит неудачу с этой паникой:
panic: преобразование интерфейса: интерфейс is int, а не main.MyInt
Причина этого указана в разделе типа утверждения спецификации:
Для выражения x типа интерфейса и типа
T
первичное выражениеx.(T)
утверждает, чтоx
неnil
и что значение, хранящееся вx
, имеет типT
. Обозначениеx.(T)
называется утверждением типа. Точнее, еслиT
не является типом интерфейса,x.(T)
утверждает, что динамический типx
идентичен типуT
.
Итак, int
должен быть идентичен MyInt
. В правилах type identity указано, что
(среди других правил):
Два именованных типа идентичны, если их имена типов возникают в том же TypeSpec.
Поскольку int
и MyInt
имеют разные объявления (TypeSpecs), они не равны
и утверждение терпит неудачу. Когда вы утверждаете a
- int
, это утверждение работает.
То, что вы делаете, невозможно.
Бонус:
Фактическая проверка происходит в в этом коде, который просто проверяет, являются ли оба типа то же, что и ожидалось.