Skip to content

Instantly share code, notes, and snippets.

@givensuman
Last active October 14, 2025 16:21
Show Gist options
  • Save givensuman/7d2782fa71a1d18414924fabfb39ae38 to your computer and use it in GitHub Desktop.
Save givensuman/7d2782fa71a1d18414924fabfb39ae38 to your computer and use it in GitHub Desktop.
Implementation of the Observer design pattern
package main
import "fmt"
// UpdateLogger is a concrete type which can observe
// Observable and log their updates
type UpdateLogger struct {
message string
}
// newUpdateLogger creates a new UpdateLogger object
func newUpdateLogger(message any) *UpdateLogger {
return &UpdateLogger{
message: fmt.Sprintf("%v", message),
}
}
// var _ Observer[string] = (*UpdateLogger)(nil)
// update satisfies the Observer interface
func (u *UpdateLogger) update(data string) {
fmt.Println(u.message, data)
}
func main() {
item := newSubject("Hello")
happyLogger := newUpdateLogger("Yay, an update!: ")
sadLogger := newUpdateLogger("Aww, an update...: ")
item.subscribe(happyLogger)
item.subscribe(sadLogger)
item.notifySubscribers()
item.updateData("Goodbye")
item.notifySubscribers()
}
package main
// Observable is an element which can be observed
type Observable[T any] interface {
subscribe(o Observer[T])
unsubscribe(o Observer[T]) error
notifySubscribers()
}
// Observer is an element which can observe an Observable
type Observer[T any] interface {
update(data T)
}
package main
import "errors"
// Subject is a concrete instance
// of an Observable
type Subject[T any] struct {
observers []Observer[T]
data T
}
// newSubject creates a new Subject object
func newSubject[T any](data T) *Subject[T] {
return &Subject[T]{
observers: []Observer[T]{},
data: data,
}
}
// var _ Observable[string] = (*Subject[string])(nil)
func (s *Subject[T]) updateData(data T) {
s.data = data
}
// subscribe an observer to the subject
func (s *Subject[T]) subscribe(o Observer[T]) {
s.observers = append(s.observers, o)
}
// unsubscribe an observer from the subject
func (s *Subject[T]) unsubscribe(o Observer[T]) error {
for i := range s.observers {
if s.observers[i] == o {
// Remove the observer from the slice
s.observers[i] = s.observers[len(s.observers)-1]
s.observers = s.observers[:len(s.observers)-1]
return nil
}
}
return errors.New("Observer not found")
}
// notifySubscribers notifies all observers of
// the state of the observable
func (s *Subject[T]) notifySubscribers() {
for i := range s.observers {
s.observers[i].update(s.data)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment