Em Go, se você definir um novo tipo, por exemplo:
type MyInt int
Você não pode então passar um MyInt
para uma função que espera um int, ou vice-versa:
func test(i MyInt) {
//do something with i
}
func main() {
anInt := 0
test(anInt) //doesn't work, int is not of type MyInt
}
Bem. Mas por que então o mesmo não se aplica às funções? por exemplo:
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
}
Agora, não estou reclamando porque me poupa ter que lançar explicitamente newfunc
para digitar MyFunc
, como eu teria que fazer no primeiro exemplo; apenas parece inconsistente. Tenho certeza de que há um bom motivo para isso; alguém pode me esclarecer?
A razão pela qual pergunto é principalmente porque gostaria de encurtar alguns dos meus tipos de função bastante longos desta forma, mas quero ter certeza de que é esperado e aceitável fazer isso :)
type
é muito mais útil no Go do que no Scala. O Scala possui apenas aliases de tipo, infelizmente.Respostas:
Acontece que este é um mal-entendido que eu tive sobre como Go lidou com os tipos, que pode ser resolvido lendo a parte relevante da especificação:
http://golang.org/ref/spec#Type_identity
A distinção relevante que eu desconhecia era a de tipos nomeados e não nomeados .
Tipos nomeados são tipos com um nome, como int, int64, float, string, bool. Além disso, qualquer tipo que você criar usando 'type' é um tipo nomeado.
Tipos sem nome são aqueles como [] string, map [string] string, [4] int. Eles não têm nome, simplesmente uma descrição correspondente a como devem ser estruturados.
Se você comparar dois tipos nomeados, os nomes devem corresponder para que sejam intercambiáveis. Se você comparar um tipo nomeado e um não nomeado, contanto que a representação subjacente corresponda , você está pronto para começar!
por exemplo, dados os seguintes tipos:
o seguinte é inválido:
o seguinte está bom:
Estou um pouco arrasado por não saber disso antes, então espero que isso esclareça um pouco o tipo de cotovia para outra pessoa! E significa muito menos elenco do que eu pensava inicialmente :)
fonte
is := make(MySlice, 0); m := make(MyMap)
, que é mais legível em alguns contextos.Tanto a pergunta quanto a resposta são bastante esclarecedoras. No entanto, gostaria de apresentar uma distinção que não está clara na resposta de Lytnus.
Tipo com nome é diferente do tipo sem nome .
Variável do tipo nomeado é atribuído a variável do Tipo Sem nome , vice-versa.
Variáveis de diferentes tipos nomeados não podem ser atribuídas umas às outras.
http://play.golang.org/p/uaYHEnofT9
fonte