Goworkinggo1

Interfaces and methods

An interface is a set of method signatures; any type with those methods satisfies it β€” no implements keyword.

Go interfaces are satisfied implicitly: define Area() float64 on a type and it *is* a Shape, enabling polymorphism, fmt.Stringer, and switch v := x.(type) dispatch.

A method is just a function with a receiver β€” a value the function is attached to, written before the name: func (c Circle) Area() float64. An interface is a named set of method signatures, like type Shape interface { Area() float64 }. Any type whose methods include every signature in the interface satisfies it.

What makes Go distinctive is that satisfaction is implicit. There is no implements clause and no declaration linking a type to an interface. If Circle has an Area() float64 method, then Circle is a Shape β€” automatically, and even for interfaces defined in packages the author never saw. This decouples the concrete types from the abstractions that consume them.

Polymorphism through interface values

A variable of interface type can hold any value whose type satisfies the interface. Store a Circle and a Rectangle in the same []Shape and call .Area() on each β€” Go dispatches to the right method at runtime. The interface value carries both the concrete value and its type, so the call always reaches the correct implementation.

Stringer: the print contract

The standard library defines fmt.Stringer as interface { String() string }. When you pass a value to fmt.Println or %v, the fmt package checks whether it satisfies Stringer; if so, it calls String() for the text. Giving your type a String() method is the idiomatic way to control how it prints β€” no special registration, just the method.

Recovering the concrete type

Sometimes you need the underlying value back out of an interface. A type assertion v, ok := x.(Circle) tests for one specific type. A type switch switch v := x.(type) branches across several, binding v to the matched concrete type in each case. The empty interface interface{} (or its alias any) holds any value, and a type switch is how you safely inspect what is inside.

Try it 5 examples

A Shape interface two types satisfy

Gointro
0ms
circle area: 12.57rectangle area: 12.00
Reference Β· output compiled offline, not runnable in-browser

The same Shape variable s first holds a Circle then a Rectangle, and each s.Area() call dispatches to that concrete type's method β€” neither type ever declares it implements Shape. Implicit satisfaction is what makes this polymorphism work.