blogpost code for https://www.bartfokker.nl/posts/decorators/
package main | |
import ( | |
"fmt" | |
"log" | |
"os" | |
"sync" | |
"time" | |
) | |
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) | |
}(time.Now()) | |
// 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)), | |
WrapCache(&sync.Map{}), | |
)(a) | |
a.Add(10, 20) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment