Go Tutorial · Functions and Methods · Lesson 20 of 30
Go Interfaces
Implicit interfaces, polymorphism, the empty interface and type switches.
Implicit implementation
An interface lists method signatures. A type satisfies it automatically by having those methods — there's no implements keyword:
package main
import (
"fmt"
"math"
)
type Shape interface {
Area() float64
}
type Circle struct{ R float64 }
func (c Circle) Area() float64 { return math.Pi * c.R * c.R }
type Square struct{ Side float64 }
func (s Square) Area() float64 { return s.Side * s.Side }
func main() {
shapes := []Shape{Circle{R: 1}, Square{Side: 2}}
total := 0.0
for _, s := range shapes {
fmt.Printf("%T area %.2f\n", s, s.Area())
total += s.Area()
}
fmt.Printf("total %.2f\n", total)
}
Output
main.Circle area 3.14 main.Square area 4.00 total 7.14
Run this on your computer — see “Get Started” for setup.
Small interfaces are idiomatic: io.Reader and io.Writer have one method each, and fmt.Stringer is just String() string.
any and type switches
any (alias for interface{}) holds a value of any type. A type switch or type assertion gets the concrete type back:
package main
import (
"fmt"
"strings"
)
func describe(v any) string {
switch t := v.(type) {
case int:
return fmt.Sprintf("int %d (doubled %d)", t, t*2)
case string:
return "string " + strings.ToUpper(t)
case nil:
return "nil"
default:
return fmt.Sprintf("something else: %T", t)
}
}
func main() {
for _, v := range []any{42, "hello", 3.5, []int{1, 2}, nil} {
fmt.Println(describe(v))
}
var x any = "text"
if s, ok := x.(string); ok {
fmt.Println("it's a string of length", len(s))
}
}
Output
int 42 (doubled 84) string HELLO something else: float64 something else: []int nil it's a string of length 4
Run this on your computer — see “Get Started” for setup.
Test yourself
How does a Go type declare that it implements an interface?
With the implements keywordIt doesn't — having the methods is enoughBy embedding the interfaceWith an annotation
Show answer
Answer: It doesn't — having the methods is enough