Golang interfaces

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())
}