Interfaces are satisfied implicitly
An interface type is a set of method signatures: type Shape interface { Area() float64 }. Any type that has those methods automatically satisfies the interface — there is no implements keyword and no declaration linking the two. Rect never mentions Shape; it just happens to have an Area() float64 method.
A variable of interface type can hold any value whose type satisfies it. Calling a method on the interface runs the method of whatever concrete type is inside at that moment — dynamic dispatch. This lets you write one function, totalArea(shapes []Shape), that works for rectangles, circles and any shape somebody adds next year.
package main
import (
"fmt"
"math"
)
type Shape interface {
Area() float64
Name() string
}
type Rect struct{ W, H float64 }
func (r Rect) Area() float64 { return r.W * r.H }
func (r Rect) Name() string { return "rect" }
type Circle struct{ R float64 }
func (c Circle) Area() float64 { return math.Pi * c.R * c.R }
func (c Circle) Name() string { return "circle" }
func totalArea(shapes []Shape) float64 {
total := 0.0
for _, s := range shapes {
fmt.Printf("%-6s %6.2f\n", s.Name(), s.Area()) // dispatch to the concrete type
total += s.Area()
}
return total
}
func main() {
shapes := []Shape{Rect{3, 4}, Circle{1}, Rect{W: 2, H: 2}}
fmt.Printf("total %6.2f\n", totalArea(shapes))
var s Shape = Circle{2} // an interface variable
fmt.Printf("%T %.2f\n", s, s.Area())
}rect 12.00
circle 3.14
rect 4.00
total 19.14
main.Circle 12.57Add a Triangle{Base, Height float64} type with both methods and put one in shapes. You do not touch Shape or totalArea at all.
Square does not implement Shape (missing method Name)
package main
import "fmt"
type Shape interface {
Area() float64
Name() string
}
type Square struct{ Side float64 }
func (s Square) Area() float64 { return s.Side * s.Side }
func main() {
var s Shape = Square{2}
fmt.Println(s.Area())
}# command-line-arguments
./main.go:15:16: cannot use Square{…} (value of struct type Square) as Shape value in variable declaration: Square does not implement Shape (missing method Name)Satisfaction is implicit but still checked at compile time. The moment you put a Square where a Shape is needed, the compiler checks the method set and names the first missing method.
Add the missing method with the exact signature. A common trick to get this check at the type declaration rather than at a distant call site is var _ Shape = Square{} at package level.
package main
import "fmt"
type Shape interface {
Area() float64
Name() string
}
type Square struct{ Side float64 }
func (s Square) Area() float64 { return s.Side * s.Side }
func (s Square) Name() string { return "square" }
var _ Shape = Square{} // compile-time check
func main() {
var s Shape = Square{2}
fmt.Println(s.Area())
}Counter does not implement Incrementer (method Inc has pointer receiver)
package main
import "fmt"
type Incrementer interface {
Inc()
}
type Counter struct{ N int }
func (c *Counter) Inc() { c.N++ }
func main() {
c := Counter{}
var i Incrementer = c
i.Inc()
fmt.Println(c.N)
}# command-line-arguments
./main.go:15:22: cannot use c (variable of struct type Counter) as Incrementer value in variable declaration: Counter does not implement Incrementer (method Inc has pointer receiver)The method is declared on *Counter, so only a *Counter has it in its method set. A plain Counter stored in an interface is a copy the interface owns — calling a pointer method on it could never update c, so Go refuses rather than silently modifying a hidden copy.
Store a pointer in the interface.
package main
import "fmt"
type Incrementer interface {
Inc()
}
type Counter struct{ N int }
func (c *Counter) Inc() { c.N++ }
func main() {
c := Counter{}
var i Incrementer = &c
i.Inc()
fmt.Println(c.N)
}