В Go, если вы определяете новый тип, например:
type MyInt int
Затем вы не можете передать a MyInt
функции, ожидающей int, или наоборот:
func test(i MyInt) {
//do something with i
}
func main() {
anInt := 0
test(anInt) //doesn't work, int is not of type MyInt
}
Хорошо. Но почему тогда то же самое не относится к функциям? например:
type MyFunc func(i int)
func (m MyFunc) Run(i int) {
m(i)
}
func run(f MyFunc, i int) {
f.Run(i)
}
func main() {
var newfunc func(int) //explicit declaration
newfunc = func(i int) {
fmt.Println(i)
}
run(newfunc, 10) //works just fine, even though types seem to differ
}
Теперь я не жалуюсь, потому что это избавляет меня от необходимости явно приводить newfunc
тип MyFunc
, как в первом примере; это просто кажется непоследовательным. Я уверен, что для этого есть веская причина; кто-нибудь может просветить меня?
Причина, по которой я спрашиваю, в основном потому, что я хотел бы таким образом сократить некоторые из моих довольно длинных типов функций, но я хочу убедиться, что это ожидаемо и приемлемо :)
type
гораздо полезнее в Go, чем в Scala. Увы, в Scala есть только псевдонимы типов.Ответы:
Оказывается, у меня возникло недоразумение по поводу того, как Go работает с типами, и его можно решить, прочитав соответствующую часть спецификации:
http://golang.org/ref/spec#Type_identity
Соответствующее различие, о котором я не знал, было различие именованных и безымянных типов.
Именованные типы - это типы с именем, например int, int64, float, string, bool. Кроме того, любой тип, который вы создаете с помощью 'type', является именованным типом.
К неназванным типам относятся такие, как [] строка, карта [строка] строка, [4] int. У них нет названия, просто описание, соответствующее тому, как они должны быть структурированы.
Если вы сравниваете два именованных типа, имена должны совпадать, чтобы они могли быть взаимозаменяемыми. Если вы сравниваете именованный и безымянный тип, то до тех пор, пока базовое представление совпадает , все в порядке!
например, учитывая следующие типы:
следующее неверно:
следующее нормально:
Я немного расстроен, я не знал этого раньше, поэтому я надеюсь, что это немного проясняет типаж для кого-то другого! А значит кастинга гораздо меньше, чем я думал сначала :)
источник
is := make(MySlice, 0); m := make(MyMap)
, который в некоторых контекстах более удобочитаем.И вопрос, и ответ довольно поучительны. Однако я хотел бы выделить различие, которое неясно в ответе Литнуса.
Именованный тип отличается от безымянного типа .
Переменная именованного типа присваивается переменной безымянного типа , и наоборот.
Переменные другого именованного типа не могут быть присвоены друг другу.
http://play.golang.org/p/uaYHEnofT9
источник