package mainimport ( "fmt" "math")// Here's a basic interface for geometric shapes.type geometry interface { area() float64 perim() float64}// For our example we'll implement this interface on rect and circle types.type rect struct { width, height float64}type circle struct { radius float64}// To implement an interface in Go, we just need to implement// all the methods in the interface. Here we implement geometry on rects.func (r rect) area() float64 { return r.width * r.height}func (r rect) perim() float64 { return 2*r.width + 2*r.height}// The implementation for circles.func (c circle) area() float64 { return math.Pi * c.radius * c.radius}func (c circle) perim() float64 { return 2 * math.Pi * c.radius}// If a variable has an interface type, we can call methods// that are in the named interface. Here's a generic measure// function taking advantage of this to work on any geometry.func measure(g geometry) { fmt.Println(g) fmt.Println(g.area()) fmt.Println(g.perim())}func main() { r := rect{width: 3, height: 4} c := circle{radius: 5} // The circle and rect struct types both implement // the geometry interface so we can use instances of // these structs as arguments to measure. measure(r) measure(c)}
// Sometimes it's useful to know the runtime type of an interface value.// One option is using a type assertion as shown here.func detectCircle(g geometry) { if c, ok := g.(circle); ok { fmt.Println("circle with radius", c.radius) }}func main() { r := rect{width: 3, height: 4} c := circle{radius: 5} detectCircle(r) // Prints nothing (not a circle) detectCircle(c) // Prints: circle with radius 5}
Type assertions use the syntax value, ok := interfaceVar.(ConcreteType). The ok boolean tells you if the assertion succeeded.
Interfaces are implemented implicitly. There’s no implements keyword — if a type has all the required methods, it implements the interface automatically.
// rect implements geometry just by having area() and perim() methodsfunc (r rect) area() float64 { ... }func (r rect) perim() float64 { ... }
2
Interface types
Variables can be declared with an interface type. They can hold any value that implements that interface.
var g geometry = rect{width: 3, height: 4}g = circle{radius: 5} // Also valid
3
Method calls
You can call any method defined in the interface on a variable of that interface type.
func measure(g geometry) { g.area() // Calls the appropriate implementation g.perim() // Based on the runtime type}