Interfaces, interfaz {}, conversiones
Una interfaz en Go especifica unconjunto de métodos. Se dice que cualquier tipo que implemente este conjunto de métodosimplementar la interfaz.
Una interfaz se implementa de forma implícita. No hayimplementospalabra clave, utilizada en otros idiomas. Si un tipo define todo el conjunto de métodos de una interfaz, lo implementa. Se llama tipado estructural, el equivalente en tiempo de compilación deescribiendo pato.
Si camina como un pato, nada como un pato y grazna como un pato, es un pato.
Importante: en Go, la interfaz abstrae un conjunto de métodos (acciones), no datos.
Ejemplo
El siguiente ejemplo tomado deCómo usar interfaces en Goilustra una interfaz básica de un animal que puede hablar y diferentes estructuras que satisfacen la interfaz:
type Animal interface {
Speak() string
}
type Dog struct {
}
func (d Dog) Speak() string {
return “Woof!”
}
type Cat struct {
}
func (c Cat) Speak() string {
return “Meow!”
}
type Llama struct {
}
func (l Llama) Speak() string {
return “???”
}
type JavaProgrammer struct {
}
func (j JavaProgrammer) Speak() string {
return “Design patterns!”
}
Puedes construir un [] Animal y correrSpeak()
sobre su contenido:
func main() {
animals := []Animal{Dog{}, Cat{}, Llama{}, JavaProgrammer{}}
for _, animal := range animals {
fmt.Println(animal.Speak())
}
}
La interfaz vacía
losAnimal
La interfaz es pequeña y agradable, pero hay algo aún más simple, aunque un concepto algo complejo de entender para los principiantes: la interfaz vacía.
interface{}
es la interfaz Go Empty, un concepto clave. Cada tipo lo implementa por definición.
Una interfaz es un tipo, por lo que puede definir, por ejemplo:
type Dog struct {
Age interface{}
}
y también puede pasar un tipo de interfaz vacío como parámetro de función:
func Eat(t interface{}) {
// ...
}
Aceptarinterface{}
no significa que la función acepta cualquier tipo, sino que significa que Eat acepta un valor deinterface{}
escribe.
En tiempo de ejecución, Go convertirá el valor real pasado a uninterface{}
valor.
Si define un campo en una estructura con tipointerface{}
, puede asignarle un valor de cualquier tipo. Por ejemplo:
package main
import “fmt”
type Dog struct {
Age interface{}
}
func main() {
dog := Dog{}
dog.Age = “3”
fmt.Printf("%#v %T\n", dog.Age, dog.Age)
<span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span> = <span style="color:#ae81ff">3</span>
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Printf</span>(<span style="color:#e6db74">"%#v %T\n"</span>, <span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span>, <span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span>)
<span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span> = <span style="color:#e6db74">"not really an age"</span>
<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Printf</span>(<span style="color:#e6db74">"%#v %T"</span>, <span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span>, <span style="color:#a6e22e">dog</span>.<span style="color:#a6e22e">Age</span>)
}
huellas dactilares
"3" string
3 int
"not really an age" string
Por supuesto, esto no se limita a los tipos básicos: puede almacenar un segmento, un mapa, cualquier estructura personalizada allí.
Cómo se representa la interfaz internamente
Internamente, una interfazvalorson doswords
, conjuntos de bytes.
Una palabra apunta al tipo de valor subyacente. Una palabra apunta a los datos.
Conversiones
Cuando lo hicimosanimals := []Animal{Dog{}, Cat{}, Llama{}, JavaProgrammer{}}
anteriormente, Go convertía automáticamente todos nuestros tipos de animales específicos en un tipo de Animal. Cada elemento de esa porción ahora es de tipo Animal, con el tipo subyacente apuntando a la especie específica, como Perro, Gato y Llama.
Pero si un método acepta[]interface{}
por ejemplo, no podemos simplemente pasaranimals
a él, porque el tipo no coincide. Necesitamos queconvertir explícitamente cadaAnimal
a unainterface{}
antes, con un bucle, como se describe en el¿Puedo convertir una [] T en una [] interfaz {}PREGUNTAS MÁS FRECUENTES:
t := []int{1, 2, 3, 4}
s := make([]interface{}, len(t))
for i, v := range t {
s[i] = v
}
Determine el tipo subyacente de uninterface{}
Si un valor es de tipointerface{}
, es posible que desee determinar el tipo subyacente. ¿Cómo? Con un interruptor encendido.(type)
, me gustaGo eficazexplica:
También se puede utilizar un conmutador para descubrir el tipo dinámico de una variable de interfaz. Este tipo de cambio utiliza la sintaxis de una aserción de tipo con la palabra clave type entre paréntesis. Si el conmutador declara una variable en la expresión, la variable tendrá el tipo correspondiente en cada cláusula. También es idiomático reutilizar el nombre en tales casos, declarando de hecho una nueva variable con el mismo nombre pero de un tipo diferente en cada caso.
var t interface{}
t = functionOfSomeType()
switch t := t.(type) {
default:
fmt.Printf("unexpected type %T\n", t) // %T prints whatever type t has
case bool:
fmt.Printf("boolean %t\n", t) // t has type bool
case int:
fmt.Printf("integer %d\n", t) // t has type int
case *bool:
fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
fmt.Printf("pointer to integer %d\n", *t) // t has type *int
}
Más tutoriales de go:
- Uso de NGINX Reverse Proxy para brindar servicios de Go
- Hacer una copia de una estructura en Go
- Los conceptos básicos de un servidor web Go
- Ordenar un tipo de mapa en Go
- Ir consejos en pocas palabras
- Explicación de las etiquetas Go
- Ir al formato de fecha y hora
- Procesamiento JSON con Go
- Ir a funciones variadas
- Hoja de referencia de Go Strings
- Explicación de la interfaz Go Empty
- Depuración de Go con VS Code y Delve
- Parámetros de devoluciones de Go Named
- Generación de cadenas y números aleatorios en Go
- Estructura del sistema de archivos de un proyecto de Go
- Algoritmo de búsqueda binaria implementado en Go
- Uso de indicadores de línea de comando en Go
- GOPATH explicado
- Cree una aplicación de línea de comandos con Go: lolcat
- Construyendo un comando CLI con Go: cowsay
- Uso de Shell Pipes con Go
- Tutorial de Go CLI: clon de la fortuna
- Enumere los archivos en una carpeta con Go
- Use Ir para obtener una lista de repositorios de GitHub
- Ve, agrega un trozo de cadenas a un archivo
- Ve, convierte una cadena en un segmento de bytes
- Visualice sus contribuciones locales de Git con Go
- Introducción a la creación de perfiles de memoria y CPU de Go
- Resolver el error "no admite la indexación" en un programa Go
- Medir el tiempo de ejecución en un programa Go
- Creación de un rastreador web con Go para detectar títulos duplicados
- Siga las mejores prácticas: ¿puntero o receptores de valor?
- Siga las mejores prácticas: ¿Debería utilizar un método o una función?
- Ir a estructuras de datos: Establecer
- Hoja de referencia de Go Maps
- Genere implementaciones para tipos genéricos en Go
- Ir a estructuras de datos: diccionario
- Ir a estructuras de datos: tabla hash
- Implementar oyentes de eventos en canales de paso
- Ir a estructuras de datos: apilar
- Ir a estructuras de datos: cola
- Ir a estructuras de datos: árbol de búsqueda binaria
- Ir a estructuras de datos: gráfico
- Ir a estructuras de datos: lista vinculada
- La guía completa de Go Data Structures
- Comparación de valores de Go
- ¿Go está orientado a objetos?
- Trabajar con una base de datos SQL en Go
- Usar variables de entorno en Go
- Ir al tutorial: API REST respaldada por PostgreSQL
- Habilitación de CORS en un servidor web Go
- Implementación de una aplicación Go en un contenedor Docker
- Por qué Go es un lenguaje poderoso para aprender como desarrollador PHP
- Ve, elimina el carácter de nueva línea io.Reader.ReadString
- Ir, cómo ver los cambios y reconstruir su programa
- Ve, cuenta los meses desde una fecha
- Acceder a los parámetros HTTP POST en Go