Golang. Interfaces


The most cumbersome for newcomers to golang are the interfaces. Here are some examples of code I took apart to “smoke” them, I hope they will help you too. The idea is to look at the code, then close it and from memory try to write from scratch according to this plan:

  • write the code through the usual functions
  • turn functions into methods
  • add an interface

Example number one:

Find the area and perimeter of a circle and rectangle from Go by Example:

package main

import ("fmt"; "math")

type geometry interface {
    area() float64
    perim() float64
}

type circle struct {
    radius float64
}

type rect struct {
    width, height float64
}

func (c circle) area() float64 {
    return math.Pi * c.radius * c.radius
}

func (c circle) perim() float64 {
    return 2 * math.Pi * c.radius
}

func (r rect) area() float64 {
    return r.width * r.height
}

func (r rect) perim() float64 {
    return (r.width + r.height) * 2
}

func measure (g geometry) {
    fmt.Println(g.area())
    fmt.Println(g.perim())
}

func main() {
    r := rect {width: 3, height: 4}
    c := circle {radius: 5}

    measure(r)
    measure(c)
}

Example number two – finding the area and perimeter of a circle and rectangle from book “An Introduction to Programming in Go” by Caleb Doxsey:

package main

import ("fmt"; "math")


type Circle struct {
    x, y, r float64
}

type Rect struct {
    x1, y1, x2, y2 float64
}

func distance(x1, y1, x2, y2 float64) float64 {
    a := x2 - x1
    b := y2 - y1
    return math.Sqrt(a*a + b*b)
}

func (c *Circle) area() float64 {
    return math.Pi * c.r * c.r
}

func (r *Rect) area() float64 {
    l := distance(r.x1, r.y1, r.x1, r.y2)
    w := distance(r.x1, r.y1, r.x2, r.y1)
    return l * w
}

func (c *Circle) perimeter() float64 {
    return 2 * math.Pi * c.r
}

func (r *Rect) perimeter() float64 {
    l := distance(r.x1, r.y1, r.x1, r.y2)
    w := distance(r.x1, r.y1, r.x2, r.y1)
    return (l + w) * 2
}

type Shape interface {
    area() float64
    perimeter() float64
}

func totalArea (shapes ...Shape) float64 {
    var area float64
    for _, s := range shapes {
        area += s.area()
    }

    return area
}

func totalPerimeter (shapes ...Shape) float64 {
    var perimeter float64

    for _, s := range shapes {
        perimeter += s.perimeter()
    }
    return perimeter
}

func main() {
    c := Circle {0, 0, 5}
    r := Rect {0, 0, 10, 10}

    fmt.Println(c.area())
    fmt.Println(r.area())
    fmt.Println(c.perimeter())
    fmt.Println(r.perimeter())
    fmt.Println(totalArea(&c, &r))
    fmt.Println(totalPerimeter(&c, &r))
}


/* Example of interfaces' fields:

type MultiShape struct {
    shapes []Shape
}

func (m *MultiShape) area() float64 {
    var area float64
    for _, s := range m.shapes {
        area += s.area()
    }
    return area
}
*/

Example number three: the animals from Jordan Orelli:

package main

import ("fmt")

type Animal interface {
    Speak() string
}

type Dog struct {}
func (d Dog) Speak() string {
    return "Woof!"
}

type Cat struct {}
func (c Cat) Speak() string {
    return "Meow!"
}

type Llama struct {}
func (l Llama) Speak() string {
    return "???"
}

type JavaProgrammer struct {}
func (j JavaProgrammer) Speak() string {
    return "Design patterns!"
}

func main() {
    animals := []Animal{ Dog{}, Cat{}, Llama{}, JavaProgrammer{} }

    for _, animal := range animals {
        fmt.Println(animal.Speak())
    }

}

And for those who want to delve into the interface hole properly, here’s article by Russ Cox.

 

 


This entry was posted in Go (en). Bookmark the permalink.

Leave a Reply

🇬🇧 Attention! Comments with URLs/email are not allowed.
🇷🇺 Комментарии со ссылками/email удаляются автоматически.