The observer pattern allows an observable to emit events to observers. The emission can either be done through channels or invoking registered callbacks.
Conventional Approach
First let's define what are Observer and Observable as interfaces.
type (Eventstruct { Data string }Observerinterface {OnNotify(Event) }Observableinterface {Register(Observer)Unregister(Observer)Notify(Event) })
Now we can create a Reporter like a news reporter that broadcast news to people.
People are acting as Audience to the event that reporter reports.
typeAudiencestruct { name string}func (a *Audience) OnNotify(e Event) { fmt.Printf("%s received breaking news! %s\n", a.name, e.Data)}
Concurrent Approach
The problem with above aproach is that it is not concurrent. The observable calls OnNotify on each observer. What if OnNotify is an expensive function? Then there will be a significant delay to relay each event. We want to make it concurrent with room for parallelism.
Now we can register variable of any data type to this observable. We implement the interface like before with few minor modifications. Notice that Notify is no longer calling a callback, it is simply passing data to observers through channel. It is up to the observers to handle the data.