tag keywords google ejemplos types casting go

types - keywords - ¿Cómo convertir a un alias de tipo en Go?



meta tags seo 2018 (4)

Ver este fragmento de patio de recreo .

Código relevante:

type somethingFuncy func(int) bool func funcy(i int) bool { return i%2 == 0 } var a interface{} = funcy func main() { _ = a.(func(int) bool) // Works fmt.Println("Awesome -- apparently, literally specifying the func signature works.") _ = a.(somethingFuncy) // Panics fmt.Println("Darn -- doesn''t get here. But somethingFuncy is the same signature as func(int) bool.") }

El primer reparto funciona, declarando explícitamente el tipo. Pero el segundo elenco entra en pánico. ¿Por qué? ¿Hay una forma limpia de convertir a una firma de función más larga?


Actualización 2017:

Con las aserciones de tipo en Go 1.9, simplemente puede agregar = donde define el tipo.

type somethingFuncy = func(int) bool

Esto le dice al compilador que somethingFuncy es un nombre alternativo para func(int) bool .


tl; dr

Para las aserciones de tipo (que usa), solo importa el tipo real. Así que somethingFuncy solo es igual a somethingFuncy y no a func(int) bool .

Explicación

Para empezar, esto no tiene nada que ver con el casting. No hay casting en marcha. Hay aserciones de tipo y conversiones de tipo .

Usted está tratando con una aseveración de tipo y está asumiendo que las mismas condiciones son válidas para las conversiones de tipo. Cometí el mismo error al leer tu pregunta, pero en realidad hay una gran diferencia en el comportamiento.

Supongamos que tiene dos tipos, digamos int y type MyInt int . Estos son convertibles ya que ambos comparten el mismo tipo subyacente (una de las reglas de conversión), así que esto funciona ( play ):

var a int = 10 var b MyInt = MyInt(a)

Ahora, supongamos que a no es del tipo int sino del tipo interface{} ( play ):

var a interface{} = int(10) var b MyInt = MyInt(a)

El compilador te dirá:

no se puede convertir una (interfaz de tipo {}) para escribir MyInt: necesita una aserción de tipo

Así que ahora ya no estamos haciendo conversiones sino afirmaciones . Necesitamos hacer esto ( play ):

var a interface{} = int(10) var b MyInt = a.(MyInt)

Ahora tenemos el mismo problema que en tu pregunta. Esta afirmación falla con este pánico:

pánico: conversión de interfaz: interfaz es int, no main.MyInt

El motivo de esto se establece en la sección de aseveraciones de tipo de la especificación:

Para una expresión x de tipo de interfaz y un tipo T , la expresión principal x.(T) afirma que x no es nil y que el valor almacenado en x es de tipo T La notación x.(T) se llama una aserción de tipo. Más precisamente, si T no es un tipo de interfaz, x.(T) afirma que el tipo dinámico de x es idéntico al tipo T

Así que int debe ser idéntico a MyInt . Las reglas de identidad de tipo establecen que (entre otras reglas):

Dos tipos con nombre son idénticos si sus nombres de tipo se originan en la misma TypeSpec.

Como int y MyInt tienen diferentes declaraciones ( TypeSpecs ) no son iguales y la aserción falla. Cuando afirmas a a int , la aserción funciona. Entonces, lo que estás haciendo no es posible.

Prima:

La verificación real ocurre en este código , que simplemente verifica si ambos tipos son iguales, como se esperaba.



Solo para completar la asombrosa respuesta de nemo, tenga en cuenta que si bien no puede saltar directamente de una interfaz (ef, interface{} ) de un tipo dinámico dado (por ejemplo, int ) a otro tipo (por ejemplo, type MyInt int ), puede hacerlo Los dos pasos uno tras otro:

  • afirma que el tipo dinámico de tu variable es lo que esperas que sea;
  • convierta el resultado de esa afirmación al tipo de su elección.

Tenga en cuenta que dado que el tipo subyacente es, como su nombre lo indica, dinámico , es una buena idea probar si la aserción de tipo tuvo éxito o no. Por otro lado, la corrección de conversión de tipo es impuesta por el compilador.

Aquí está el fragmento de su área de juego ligeramente modificado: http://play.golang.org/p/FZv06Zf7xi