Imperatives #
Golang is an imperative language, so the following flies:
package main
import (
"fmt"
"math"
)
type shape interface {
area() float64
}
type rectangle struct {
width float64
height float64
}
func (r rectangle) area() float64 {
return r.width * r.height
}
type circle struct {
radius float64
}
func (c circle) area() float64 {
return math.Pi * c.radius * c.radius
}
func printArea(shape shape) {
fmt.Println(shape.area())
}
func main() {
printArea(rectangle{width: 10, height: 5})
printArea(circle{radius: 10})
}50
314.1592653589793One of the neat things about this is that any struct that fulfills the contract automatically “extends” the interface. Among other things, this makes mocking dependency types really easy.
Embedding #
If you want to “extend” a struct in Go, you can use embedding
Go does not provide the typical, type-driven notion of subclassing, but it does have the ability to “borrow” pieces of an implementation by embedding types within a struct or interface.
package main
import "fmt"
type worker struct {
}
func (w *worker) work() {
fmt.Println("I am working!")
}
type leech struct {
worker
}
func main() {
leecher := leech{}
leecher.work()
}I am working!This also works for interfaces:
package main
type worker interface {
work()
}
type leech interface {
worker
}