DEV Community

Discussion on: Idiomatic way to implement this in golang

Collapse
mariocarrion profile image
Mario Carrion

Hello!

Another way to do this is: play.golang.org/p/tmzumHEIo2H

Which does not use embedding or types implementing all the methods but rather functionals options and a default implementation; with the big caveat the concrete implementations are not sharing state in their methods:

package main

import "fmt"

func main() {
    bef := BeforeSensor{}
    afs := AfterShutdownSensor{}

    s := NewSensor(WithBeforeSensor(&bef), WithAfterSensor(&afs), WithShutdownSensor(&afs))

    s.Process()
}

type (
    BeforeStarter interface {
        BeforeStart()
    }

    AfterStarter interface {
        AfterStart()
    }

    Shutdowner interface {
        Shutdown()
    }

    Processer interface {
        Process()
    }
)

type Sensor struct {
    before   BeforeStarter
    after    AfterStarter
    shutdown Shutdowner
    process  Processer
}

type SensorOption func(s *Sensor)

func WithBeforeSensor(b BeforeStarter) SensorOption {
    return func(se *Sensor) {
        se.before = b
    }
}

func WithAfterSensor(a AfterStarter) SensorOption {
    return func(se *Sensor) {
        se.after = a
    }
}

func WithShutdownSensor(s Shutdowner) SensorOption {
    return func(se *Sensor) {
        se.shutdown = s
    }
}

func WithProcessSensor(p Processer) SensorOption {
    return func(se *Sensor) {
        se.process = p
    }
}

func NewSensor(opts ...SensorOption) *Sensor {
    s := Sensor{
        before:   &DefaultSensor{},
        after:    &DefaultSensor{},
        process:  &DefaultSensor{},
        shutdown: &DefaultSensor{},
    }

    for _, opt := range opts {
        opt(&s)
    }

    return &s
}

func (s *Sensor) Process() {
    s.before.BeforeStart()
    s.after.AfterStart()
    s.process.Process()
    s.shutdown.Shutdown()
}

//-

type DefaultSensor struct{}

func (d DefaultSensor) BeforeStart() {
    fmt.Println("DefaultSensor BeforeStart")
}

func (d DefaultSensor) AfterStart() {
    fmt.Println("DefaultSensor AfterStart")
}

func (d DefaultSensor) Shutdown() {
    fmt.Println("DefaultSensor Shutdown")
}

func (d DefaultSensor) Process() {
    fmt.Println("DefaultSensor Process")
}

//- BeforeSensor

type BeforeSensor struct{}

func (s BeforeSensor) BeforeStart() {
    fmt.Println("OnlyBeforeSensor BeforeStart")
}

//- AfterShutdownSensor

type AfterShutdownSensor struct{}

func (s AfterShutdownSensor) AfterStart() {
    fmt.Println("AfterShutdownSensor AfterStart")
}

func (s AfterShutdownSensor) Shutdown() {
    fmt.Println("AfterShutdownSensor Shutdown")
}
Enter fullscreen mode Exit fullscreen mode