package main

import (
    "fmt"
)

type IObserver interface {
    Update()
}

type ISubject interface {
    Attach(o IObserver)
    Detach(o IObserver)
    Notify()
}



type Subject struct {
    observers map[IObserver]bool
}
func (s *Subject) Attach(o IObserver) {
    if s.observers == nil {
        s.observers = make(map[IObserver]bool)
    }
    s.observers[o] = true
}
func (s *Subject) Detach(o IObserver) {
    delete(s.observers, o)
}
func (s Subject) Notify() {
    if s.observers == nil { return }
    for o,_ := range s.observers {
        o.Update()
    }
}



type ConcreteSubject struct {
    Subject
    state int
}
func (s *ConcreteSubject) SetState(x int) {
    s.state = x
    s.Notify()
}
func (s ConcreteSubject) GetState() int {
    return s.state
}



type ConcreteObserver struct {
    name string
    subject *ConcreteSubject
    observedState int
}
func (o ConcreteObserver) Update() {
    o.observedState = o.subject.GetState()

    fmt.Println(o.name, ".Update() -> ", o.observedState)
}



func main() {
    var mySubject ConcreteSubject

    myObserverA := ConcreteObserver{"ObserverA",&mySubject,0}
    myObserverB := ConcreteObserver{"ObserverB",&mySubject,0}

    mySubject.Attach(&myObserverA)
    mySubject.Attach(&myObserverB)

    mySubject.SetState(42)
    mySubject.SetState(17)
}