Las interfaces en Go pueden introducir ambigüedad sobre el tipo subyacente.
De hecho, la interfaz vacía puede contener cualquier valor concreto (incluidos los primitivos).
Una aserción de tipo nos permite extraer el valor concreto subyacente del valor de interfaz usando esta sintaxis: interfaceVariable.(concreteType).
Si asignamos el resultado de esta sentencia a un solo valor, afirmamos que la variable de interfaz contiene un valor del tipo concreto. Como resultado, puede provocar un panic en tiempo de ejecución si el valor de interfaz no tiene el tipo concreto especificado. Por ejemplo:
var input interface{} = 12
str := input.(string) // panic at runtime since input is not a string!
Podemos comprobar si un valor de interfaz contiene un tipo concreto específico usando los dos valores de retorno de la aserción de tipo: el valor subyacente y un valor booleano que indica si la aserción tuvo éxito. Por ejemplo:
str, ok := input.(string) // no panic if input is not a string
Si input contiene un string, entonces str será el valor subyacente y ok será verdadero.
Si input no contiene un string, entonces str será el valor cero del tipo string (es decir, "", la cadena vacía) y ok será falso.
En ningún caso se produce un panic.
Es común ver este tipo de expresión:
str, ok := input.(string)
if !ok {
str = "a default value"
}
Un switch de tipo puede realizar varias aserciones de tipo seguidas.
Tiene la misma sintaxis que una aserción de tipo (interfaceVariable.(concreteType)), pero en lugar de un concreteType específico usa la palabra clave type.
Aquí hay un ejemplo:
var i interface{} = 12 // try: 12.3, true, int64(12), []int{}, map[string]int{}
switch v := i.(type) {
case int:
fmt.Printf("the integer %d\n", v)
case string:
fmt.Printf("the string %s\n", v)
default:
fmt.Printf("type, %T, not handled explicitly: %#v\n", v, v)
}