Una aserción de tipo extrae el tipo concreto de un valor de interfaz, y un cambio de tipo ramifica según el tipo subyacente de una interfaz. Son la forma de recuperar información de tipo específica de una interfaz (especialmente la interfaz vacía / any).
Aserción de tipo — extrae un tipo concreto
var i interface{} = "hello" // an interface holding a string
s := i.(string) // assert it's a string → s = "hello"
fmt.Println(s)
n := i.(int) // ❌ PANIC — i is not an int (wrong assertion)
La sintaxis i.(Type) aserta que la interfaz i contiene un valor de Type y lo extrae. Pero una aserción incorrecta entra en pánico — por lo que normalmente usas la forma segura con coma-ok.
La forma segura coma-ok
s, ok := i.(string)
if ok {
fmt.Println("it's a string:", s) // ok = true, s = the value
} else {
fmt.Println("not a string") // ok = false, s = zero value, NO panic
}
La forma de dos valores retorna el valor más un booleano — ok es falso (en lugar de entrar en pánico) si la aserción falla. Siempre prefiere esto a menos que estés seguro del tipo.
Cambio de tipo — ramifica según múltiples tipos posibles
func describe(i interface{}) string {
switch v := i.(type) { // the special .(type) form, only in a switch
case int:
return fmt.Sprintf("int: %d (doubled: %d)", v, v*2)
case string:
return fmt.Sprintf("string of length %d", len(v))
case bool:
return fmt.Sprintf("bool: %t", v)
case nil:
return "nil value"
default:
return fmt.Sprintf("unknown type: %T", v)
}
}
describe(42) // "int: 42 (doubled: 84)"
describe("hi") // "string of length 2"
La forma switch v := i.(type) verifica el tipo subyacente y vincula v (tipificada apropiadamente en cada caso). Es la forma limpia de manejar una interfaz que podría contener varios tipos.
Asertando tipos de interfaz también
// assert that a value implements a specific interface
if w, ok := i.(io.Writer); ok {
w.Write([]byte("data")) // use it as an io.Writer if it satisfies that interface
}
Cuándo necesitas estos
✓ Processing values of unknown type (interface{}/any) — JSON, generic handlers
✓ Checking if a value implements an optional interface (e.g. io.Closer)
✓ Handling heterogeneous data
⚠️ Often a sign you could use generics or better-typed interfaces instead — don't overuse
Por qué es importante
Las aserciones de tipo y los cambios de tipo son herramientas esenciales para trabajar con valores de interfaz — recuperar información de tipo concreto de interface{}/any o verificar si un valor satisface una interfaz particular.
Son necesarios cuando se manejan datos de tipos desconocidos o variados (analizar JSON dinámico, procesamiento genérico, verificaciones de interfaz opcional como "¿esto implementa io.Closer?").
Comprender la distinción pánico-vs-seguro es crítico: una aserción simple i.(T) entra en pánico en caso de discrepancia, mientras que la forma coma-ok v, ok := i.(T) reporta seguramente el fallo — usar la forma segura es una práctica clave para evitar crashes en tiempo de ejecución.
El cambio de tipo maneja elegantemente múltiples tipos posibles.
Conocer estos (y que el uso intensivo a menudo señala que deberías recurrir a genéricos o diseños mejor tipificados en su lugar) es importante para Go seguro e idiomático y un tema común en entrevistas, ya que las interfaces y la interfaz vacía son tan centrales en el lenguaje.
