En Go, si define un nuevo tipo, por ejemplo:
type MyInt int
Entonces no puede pasar un MyInt
a una función esperando un int, o viceversa:
func test(i MyInt) {
//do something with i
}
func main() {
anInt := 0
test(anInt) //doesn't work, int is not of type MyInt
}
Multa. Pero, ¿por qué entonces no se aplica lo mismo a las funciones? p.ej:
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
}
Ahora, no me quejo porque me ahorra tener que lanzar explícitamente newfunc
para escribir MyFunc
, como tendría que hacer en el primer ejemplo; simplemente parece inconsistente. Estoy seguro de que hay una buena razón para ello; ¿Alguien puede iluminarme?
La razón por la que pregunto es principalmente porque me gustaría acortar algunos de mis tipos de funciones bastante largos de esta manera, pero quiero asegurarme de que sea esperado y aceptable para hacer esto :)
type
es bastante más útil en Go que en Scala. Scala solo tiene alias de tipo, por desgracia.Respuestas:
Resulta que este es un malentendido que tuve sobre cómo Go manejó los tipos, que se puede resolver leyendo la parte relevante de la especificación:
http://golang.org/ref/spec#Type_identity
La distinción relevante que no era consciente de que era de nombre y sin nombre tipos.
Nombrados tipos son tipos con un nombre, como int, Int64, float, string, int. Además, cualquier tipo que cree utilizando 'tipo' es un tipo con nombre.
Los tipos sin nombre son aquellos como [] string, map [string] string, [4] int. No tienen nombre, simplemente una descripción correspondiente a cómo se van a estructurar.
Si compara dos tipos con nombre, los nombres deben coincidir para que sean intercambiables. Si compara un tipo con nombre y uno sin nombre, siempre que la representación subyacente coincida , ¡está listo para comenzar!
por ejemplo, dados los siguientes tipos:
lo siguiente no es válido:
lo siguiente está bien:
Estoy un poco destrozado, no lo sabía antes, ¡así que espero que eso aclare un poco el tipo de alondra para alguien más! Y significa mucho menos casting de lo que pensé al principio :)
fuente
is := make(MySlice, 0); m := make(MyMap)
, que es más legible en algunos contextos.Tanto la pregunta como la respuesta son bastante esclarecedoras. Sin embargo, me gustaría plantear una distinción que no está clara en la respuesta de lytnus.
El tipo con nombre es diferente del tipo sin nombre .
La variable de tipo con nombre se puede asignar a la variable de tipo sin nombre , y viceversa.
Las variables de diferentes tipos con nombre no se pueden asignar entre sí.
http://play.golang.org/p/uaYHEnofT9
fuente