Lecciones del módulo (2/5)
Aserción de tipo
Una aserción de tipo extrae el tipo concreto de un valor de interfaz.
Lo necesita cuando tiene un interface{} (o una interfaz "alta") en
mano y es necesario tratarlo como su tipo específico para acceder a campos o
métodos no presentes en la interfaz.
Sintaxis
var i interface{} = "ciao"
s := i.(string) // "panic" form: panics if it's not a string
s, ok := i.(string) // "comma ok" form: ok = false if it's not a stringDos formas, dos semánticas:
| Formulario | Éxito | Fracaso |
|---|---|---|
| CÓDIGOPH0 | v = valor de tipo T | pánico en tiempo de ejecución |
| CÓDIGOPH2 | CÓDIGOPH3, CÓDIGOPH4 | v = valor cero de T, ok=false |
Formulario "Coma ok": el más seguro
var i interface{} = 42
if s, ok := i.(string); ok {
fmt.Println("è stringa:", s)
} else {
fmt.Println("non è stringa, ignoro")
}ok le permite manejar el caso de "tipo incorrecto" sin pánico. es el
patrón idiomático en la gran mayoría de los casos.
Aserción a una interfaz
La afirmación no funciona sólo en tipos concretos, sino también en otros. interfaces:
type Closer interface { Close() error }
func tryClose(x interface{}) {
if c, ok := x.(Closer); ok {
c.Close()
}
}Un patrón muy común en la biblioteca estándar: "si mi entrada también es
un io.Closer, llame a Cerrar al final".
Afirmación sobre punteros versus valores
La aserción debe coincidir EXACTAMENTE con el tipo dinámico:
type Cat struct{}
func (c *Cat) Meow() {}
var a interface{} = &Cat{}
c1, ok := a.(*Cat) // ok = true
c2, ok := a.(Cat) // ok = false: it holds *Cat, not Cat*Cat y Cat son tipos distintos para el sistema de tipos.
Cuándo usar aserción versus cambio de tipo
- Solo 1 tipo posible, verificación de "detección de características" (por ejemplo, conversión a una interfaz opcional): afirmación de tipo con
comma ok. - 2+ tipos posibles, envío a través de múltiples ramas: tipo switch (próxima lección).
Pruébalo
Utilice el patrón de coma ok para extraer una cadena de i.
Mostrar pista
Sintaxis: `v, ok := i.(T)`.
Solución disponible después de 3 intentos
Escriba aserción en int sin coma (supongamos que i contiene un int).
Mostrar pista
Sin `ok` se supone que el tipo es seguro; de lo contrario, pánico.
Solución disponible después de 3 intentos
¿Qué sucede con `s := i.(string)` si contiene un int?
var i interface{} = 42
s := i.(string)Resumen
v := i.(T): pánico si el tipo dinámico ≠ T.v, ok := i.(T): patrón seguro, consultarok.- Funciona también contra otra interfaz ("detección de funciones").
Ty*Tson tipos distintos de afirmación.- 1 tipo → afirmación; 2+ tipos → interruptor de tipo.