Chain of Responsibility Pattern in Go
Furkan Aksoy
Posted on May 21, 2024
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.
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{}
}
}
}
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!
Posted on May 21, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.