Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
package main
import (
type Adder interface {
Add(x, y int) int
type AdderFunc func(x, y int) int
func (a AdderFunc) Add(x, y int) int {
return a(x, y)
// Middleware function, this function takes in a `Adder` and returns a new `Adder`.
type AdderMiddleware func(Adder) Adder
func WrapLogger(logger *log.Logger) AdderMiddleware {
return func(a Adder) Adder {
// Using `AdderFunc` to implement the `Adder` interface.
fn := func(x, y int) (result int) {
defer func(t time.Time) {
logger.Printf("took=%v, x=%v, y=%v, result=%v", time.Since(t), x, y, result)
// Propogate call to original adder
return a.Add(x, y)
// Return a new `Adder` wrapped with the loggin functionality
return AdderFunc(fn)
func WrapCache(cache *sync.Map) AdderMiddleware {
return func(a Adder) Adder {
fn := func(x, y int) int {
key := fmt.Sprintf("x=%dy=%d", x, y)
val, ok := cache.Load(key)
if ok {
return val.(int)
result := a.Add(x, y)
cache.Store(key, result)
return result
return AdderFunc(fn)
func Chain(outer AdderMiddleware, middleware ...AdderMiddleware) AdderMiddleware {
return func(a Adder) Adder {
topIndex := len(middleware) - 1
for i := range middleware {
a = middleware[topIndex-i](a)
return outer(a)
func main() {
var a Adder = AdderFunc(
func(x, y int) int {
return x + y
a = Chain(
WrapLogger(log.New(os.Stdout, "test ", 1)),
a.Add(10, 20)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.