Chain of Responsibility Pattern in Go
Tags: go, designpatterns, backend, programming
Published: 2024-05-21 19:00:07

The Chain of Responsibility Pattern is a behavioral design pattern that allows an object to pass a request along a chain of handlers. The chain of handlers can either handle the request or pass it on to the next handler in the chain. The request is passed along the chain until it is handled or until it reaches the end of the chain.

In this article, we will explore the Chain of Responsibility Pattern in Go. We will create a simple example to demonstrate how the pattern works and how it can be implemented in Go.

The Chain of Responsibility Pattern is commonly used in scenarios where there are multiple objects that can handle a request, and the sender of the request does not know which object will handle the request. Examples of such scenarios include event handling, logging, and error handling.

## Example

Let's create a simple example to demonstrate the Chain of Responsibility Pattern in Go. In this example, chain will be responsible to validate the request, printing the error logs and handling the request itself.

```go
package service

import "fmt"

type Service interface {
    HelloWorld(name string) (string, error)
}

type service struct {}

func (s service) HelloWorld(name string) (string, error) {
    return fmt.Sprintf("Hello World from %s", name)
}

type validator struct {
    next Service
}

func (v validator) HelloWorld(name string) (string, error) {
    if len(name) <= 3 {
        return "", fmt.Errorf("name length must be greater than 3")
    }

    return v.next(name)
}

type logger struct {
    next Service
}

func (l logger) HelloWorld(name string) (string, error) {
    res, err := l.next(name)

    if err != nil {
        fmt.Println("error:", err)
        return res, err
    }

    fmt.Println("HelloWorld method executed successfuly")
    return res, err
}

func New() Service {
    return logger{
        next: validator {
            next: service{}
        }
    }
}
```

```go
package main

import (
    "fmt"
    "service"
)

func main() {
    s := service.New()

    res, err := s.HelloWorld("john")
    fmt.Println(res, err) // Hello World from john

    res, err := s.HelloWorld("joh")
    fmt.Println(res, err) // name length must be greater than 3 
}
```

In this example, we have created a simple service that implements the `Service` interface. The `Service` interface defines a method `HelloWorld` that takes a name as an argument and returns a greeting message.

We have also created two additional structs `validator` and `logger` that implement the `Service` interface. The `validator` struct validates the length of the name and returns an error if the length is less than or equal to 3. The `logger` struct prints the error logs and the success message when the `HelloWorld` method is executed successfully.

The `New` function creates a chain of handlers by chaining the `validator` and `logger` structs with the `service` struct. The `service` struct is the last handler in the chain and handles the request if it passes the validation.

### What is next field in this example?

The `next` field in the `validator` and `logger` structs is used to chain the handlers. The `next` field holds the next handler in the chain. When the `HelloWorld` method is called on a handler, it calls the `HelloWorld` method on the next handler in the chain using the `next` field.

## Conclusion

In this article, we explored the Chain of Responsibility Pattern in Go. We created a simple example to demonstrate how the pattern works and how it can be implemented in Go. I hope this article helps you understand the Chain of Responsibility Pattern and how it can be used in your projects. Happy coding!