Basics

Go supports method interfaces:

package main
 
import (
    "fmt"
    "math"
)
 
type Abser interface {
    Abs() float64
}
 
func main() {
    var a Abser
    f := MyFloat(-math.Sqrt2)
    v := Vertex{3, 4}
 
    a = f  // a MyFloat implements Abser
    a = &v // a *Vertex implements Abser
 
    fmt.Println(a.Abs())
}
 
type MyFloat float64
 
func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}
 
type Vertex struct {
    X, Y float64
}
 
func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

Interfaces are implemented implicitly:

package main
 
import "fmt"
 
type I interface {
    M()
}
 
type T struct {
    S string
}
 
// This method means type T implements the interface I,
// but we don't need to explicitly declare that it does so.
func (t T) M() {
    fmt.Println(t.S)
}
 
func main() {
    var i I = T{"hello"}
    i.M()
}

Handy interfaces to know about

Stringer

package main
 
import "fmt"
 
type Person struct {
    Name string
    Age  int
}
 
func (p Person) String() string {
    return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}
 
func main() {
    a := Person{"Arthur Dent", 42}
    z := Person{"Zaphod Beeblebrox", 9001}
    fmt.Println(a, z)
}

Error

package main
 
import (
    "fmt"
    "time"
)
 
type MyError struct {
    When time.Time
    What string
}
 
func (e *MyError) Error() string {
    return fmt.Sprintf("at %v, %s",
        e.When, e.What)
}
 
func run() error {
    return &MyError{
        time.Now(),
        "it didn't work",
    }
}
 
func main() {
    if err := run(); err != nil {
        fmt.Println(err)
    }
}

Reader

package main
 
import (
    "fmt"
    "io"
    "strings"
)
 
func main() {
    r := strings.NewReader("Hello, Reader!")
 
    b := make([]byte, 8)
    for {
        n, err := r.Read(b)
        fmt.Printf("n = %v err = %v b = %v\n", n, err, b)
        fmt.Printf("b[:n] = %q\n", b[:n])
        if err == io.EOF {
            break
        }
    }
}

Images

package main
 
import (
    "fmt"
    "image"
)
 
func main() {
    m := image.NewRGBA(image.Rect(0, 0, 100, 100))
    fmt.Println(m.Bounds())
    fmt.Println(m.At(0, 0).RGBA())
}