In this example we are going to force developers to use a struct type as an argument that implements a specific interface. This argument will be used in a constructor but it can also be used as in a function or method. The reason why we are doing this is because, our package is able to work with a certain struct type. The struct fields and functionality can be anything as long as it satisfies the interface.


Our example is simple. There is a fussy driver and this driver likes to drive only "A" class cars. We are going to give him everything though!


Structure


├── car
│   ├── audi.go
│   └── mercedes.go
├── driver
│   ├── car.go
│   └── driver.go
└── main.go

Files


car.go


package driver

type Car interface {
CheckClass(requiredClass string) bool
Make() string
Model() string
}

driver.go


package driver

import "log"

type Driver struct {
name string
requiredClass string
cars []Car
}

func New(name, requiredClass string, car... Car) Driver {
return Driver{
name: name,
requiredClass: requiredClass,
cars: car,
}
}

func (d Driver) Drive() {
for _, car := range d.cars {
if car.CheckClass(d.requiredClass) {
log.Println(d.name, "will drive", car.Make(), car.Model())
} else {
log.Println(d.name, "won't drive", car.Make(), car.Model())
}
}
}

audi.go


package car

type Audi struct {
// Class
Cls string
// Model
Mdl string
}

func (c Audi) CheckClass(requiredClass string) bool {
return c.Cls == requiredClass
}

func (c Audi) Make() string {
return "Audi"
}

func (c Audi) Model() string {
return c.Mdl
}

mercedes.go


package car

type Mercedes struct {
// Class
Cls string
// Model
Mdl string
}

func (c Mercedes) CheckClass(requiredClass string) bool {
return c.Cls == requiredClass
}

func (c Mercedes) Make() string {
return "Mercedes"
}

func (c Mercedes) Model() string {
return c.Mdl
}

main.go


package main

import (
"client/internal/car"
"client/internal/driver"
)

func main() {
merc1 := car.Mercedes{
Cls: "A",
Mdl: "SL500",
}
merc2 := car.Mercedes{
Cls: "C",
Mdl: "D200",
}
audi1 := car.Audi{
Cls: "A",
Mdl: "80",
}

driver.
New("inanzzz", "A", merc1, merc2, audi1).
Drive()
}

Test


2020/04/06 18:01:54 inanzzz will drive Mercedes SL500
2020/04/06 18:01:54 inanzzz won't drive Mercedes D200
2020/04/06 18:01:54 inanzzz will drive Audi 80