Las interfaces en Go son un conjunto de métodos que un tipo debe implementar para cumplir con esta interfaz. No existe una palabra clave explícita implements: la compatibilidad es estructural, no declarativa. La asignación de un tipo que implementa a una variable de tipo de interfaz solo es posible si el tipo implementa todos los métodos de la interfaz.
Es importante: una variable de interfaz contiene dos punteros: uno a los datos (value) y otro al tipo (type).
Ejemplo de declaración e implementación:
type Printer interface { Print() } type MyPrinter struct{} func (mp MyPrinter) Print() { fmt.Println("printing...") } var p Printer = MyPrinter{} p.Print() // "printing..."
¿Qué sucederá si la variable de interfaz es igual a nil? ¿Cuál es la diferencia entre "var i interface{} = nil" y "var i interface{}"?
Una respuesta incorrecta común es "ambos valores son nil". En realidad, no es así:
var i interface{} = nil — la variable es realmente nil (type=nil, value=nil)var p *MyPrinter = nil; var i Printer = p, entonces i != nil, porque type != nil (dentro de i — type=*MyPrinter, value=nil), y muchas comprobaciones como if i == nil no funcionarán cuando lo esperas.Ejemplo:
var p *MyPrinter = nil var i Printer = p fmt.Println(i == nil) // false!
Historia
Descripción: En un servicio, el manejador de errores devolvía una interfaz con un valor nil, y los clientes consideraban el error no nulo, realizando acciones redundantes. El problema estaba en la comparación de la interfaz con nil.
Historia
Descripción: Al escribir pruebas, se comprobó erróneamente un error de tipo interfaz por igualdad a nil tras devolver una estructura con campos nil. Las pruebas no detectaron errores reales, lo que llevó a la aparición de un bug en producción.
Historia
Descripción: Al migrar de un tipo de interfaz a otro, se olvidaron de implementar todos los métodos de la nueva interfaz, ya que no había un implements explícito. El código se compilaba, pero la interfaz no se implementaba, y algunas funciones de burla dejaron de funcionar.