Interfaces in Go are a set of methods that a type must implement to be compatible with that interface. There is no explicit keyword implements: the compatibility is structural, not declarative. Assigning a implementing type to an interface type variable is only possible if the type implements all the methods of the interface.
Important: an interface variable contains two pointers — to the data (value) and to the type (type).
Example of declaration and implementation:
type Printer interface { Print() } type MyPrinter struct{} func (mp MyPrinter) Print() { fmt.Println("printing...") } var p Printer = MyPrinter{} p.Print() // "printing..."
What happens if the interface variable is equal to nil? What is the difference between "var i interface{} = nil" and "var i interface{}"?
A common misconception is that "both values are nil". In reality — they are not:
var i interface{} = nil — the variable is indeed nil (type=nil, value=nil)var p *MyPrinter = nil; var i Printer = p, then i != nil, because type != nil (inside i — type=*MyPrinter, value=nil), and many checks like if i == nil will not work when you expect them to.Example:
var p *MyPrinter = nil var i Printer = p fmt.Println(i == nil) // false!
Story
Description: In one service, the error handler returned an interface with a nil value, and clients considered the error non-null, triggering redundant actions. The problem was in comparing the interface with nil.
Story
Description: While writing tests, there was an erroneous check for the error of the interface type for equality to nil after returning a structure with nil fields. The tests did not detect actual errors, leading to a bug in production.
Story
Description: When migrating from one interface type to another, all methods of the new interface were forgotten to be implemented, as there was no explicit implements. The code compiled, but the interface was not implemented, and some mocked functions stopped working.