Skip to content

Instantly share code, notes, and snippets.

@arielsrv
Last active August 17, 2022 18:19
Show Gist options
  • Save arielsrv/dc21f674164e380db5cbc6a9e1016ab0 to your computer and use it in GitHub Desktop.
Save arielsrv/dc21f674164e380db5cbc6a9e1016ab0 to your computer and use it in GitHub Desktop.
Command pattern in go
package main
import (
"fmt"
"sync"
)
func main() {
command1 := NewCreateDirectory("/foo")
command2 := NewDeleteDirectory("/doe")
command3 := NewCreateDirectory("/gnu")
commands := make([]Command, 0)
commands = append(commands,
command1,
command2,
command3,
)
// Re-used command
invoker := NewInvoker(commands)
invoker.Execute()
// Builder
NewParallelBuilder().
Add(command1).
Add(command2).
Add(command3).
Wait()
}
type Command interface {
Execute()
}
type Invoker struct {
commands []Command
}
func NewInvoker(commands []Command) *Invoker {
return &Invoker{commands: commands}
}
func (i Invoker) Execute() {
var wg sync.WaitGroup
for _, command := range i.commands {
wg.Add(1)
go func(runnable Command) {
defer wg.Done()
runnable.Execute()
}(command)
}
wg.Wait()
}
type ParallelBuilder struct {
wg *sync.WaitGroup
commands []Command
}
func NewParallelBuilder() *ParallelBuilder {
return &ParallelBuilder{
wg: &sync.WaitGroup{},
commands: make([]Command, 0),
}
}
func (builder *ParallelBuilder) Add(command Command) *ParallelBuilder {
builder.commands = append(builder.commands, command)
builder.wg.Add(1)
return builder
}
func (builder *ParallelBuilder) Wait() {
for _, command := range builder.commands {
go func(runnable Command) {
defer builder.wg.Done()
runnable.Execute()
}(command)
}
builder.wg.Wait()
}
type CreateDirectory struct {
path string
}
func NewCreateDirectory(path string) *CreateDirectory {
return &CreateDirectory{path: path}
}
func (c CreateDirectory) Execute() {
println(fmt.Sprintf("Creating directory %s ...", c.path))
}
type DeleteDirectory struct {
path string
}
func (d DeleteDirectory) Execute() {
println(fmt.Sprintf("Deleting directory %s ...", d.path))
}
func NewDeleteDirectory(path string) *DeleteDirectory {
return &DeleteDirectory{path: path}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment