GoLang design pattern 13 - observer pattern

Observer pattern is a behavioral design pattern. This pattern allows one instance (which can be called a target object) to publish various events to other instances (observers). These observers subscribe to the target object so that they receive event notifications whenever the target object changes.

Let's take a look at an example: various goods are often out of stock on e-commerce websites. If customers are already paying attention to these goods, the out of stock of these goods will have a bad experience for them. If customers still want to buy these products, there are usually the following solutions:

  1. Customers check whether these goods are on sale at a certain frequency
  2. The e-commerce platform regularly pushes all commodity information on the shelves to users
  3. Customers only subscribe to the information of specific products they are concerned about, and they will be notified when these products are on the shelves again; Multiple customers can subscribe to the information of the same product

Option 3 is the most feasible option. This is what the observer model can do. The core components of observer mode are:

  • Subject  : The target object is an instance that publishes related events when changes occur
  • Observer  : Observers, who subscribe to the information of the target object, will receive notifications of some specific events

Usually, Subject and Observer are defined as interfaces, and the real use is their specific implementation.

UML class diagram is as follows:

  Here is an example code:


type observer interface {
	getID() string


type subject interface {
	register(Observer observer)
	deregister(Observer observer)


import "fmt"

type item struct {
	observerList []observer
	name         string
	inStock      bool

func newItem(name string) *item {
	return &item{
		name: name,

func (i *item) updateAvailability() {
	fmt.Printf("Item %s is now in stock\n", i.name)
	i.inStock = true

func (i *item) register(o observer) {
	i.observerList = append(i.observerList, o)

func (i *item) deregister(o observer) {
	i.observerList = removeFromSlice(i.observerList, o)

func (i *item) notifyAll() {
	for _, observer := range i.observerList {

func removeFromSlice(observerList []observer, observerToRemove observer) []observer {
	observerListLength := len(observerList)
	for i, observer := range observerList {
		if observerToRemove.getID() == observer.getID() {
			observerList[observerListLength-1], observerList[i] = observerList[i], observerList[observerListLength-1]
			return observerList[:observerListLength-1]
	return observerList


import "fmt"

type customer struct {
	id string

func (c *customer) update(itemName string) {
	fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName)

func (c *customer) getID() string {
	return c.id

In the above code, item is the implementation of subject and customer is the implementation of observer.

Look at the next scene class main.go:

func main() {
	shirtItem := newItem("GoLang Design Patterns")
	observerFirst := &customer{id: "robin@zhyea.com"}
	observerSecond := &customer{id: "golang@zhyea.com"}

After execution, the output contents are:

Item GoLang Design Patterns is now in stock
Sending email to customer robin@zhyea.com for item GoLang Design Patterns
Sending email to customer golang@zhyea.com for item GoLang Design Patterns

Code uploaded to GitHub:   zhyea / go-patterns / observer-pattern


Tags: Go Design Pattern

Posted on Sun, 07 Nov 2021 17:40:25 -0500 by jdavidbakr