Custom Services
Services are objects that are available to be injected into a handler's argument list. You can map a service on a Global or Request level.

Global Mapping

A Macaron instance implements the inject.Injector interface, so mapping a service is easy:
1
db := &MyDatabase{}
2
m := macaron.Classic()
3
m.Map(db) // Service will be available to all handlers as *MyDatabase
4
m.Get("/", func(db *MyDatabase) {
5
// Operations with db.
6
})
7
m.Run()
Copied!

Request-Level Mapping

Mapping on the request level can be done in a handler via *macaron.Context:
1
func MyCustomLoggerHandler(ctx *macaron.Context) {
2
logger := &MyCustomLogger{ctx.Req}
3
ctx.Map(logger) // mapped as *MyCustomLogger
4
}
5
6
func main() {
7
//...
8
m.Get("/", MyCustomLoggerHandler, func(logger *MyCustomLogger) {
9
// Operations with logger.
10
})
11
m.Get("/panic", func(logger *MyCustomLogger) {
12
// This will panic because no logger service maps to this request.
13
})
14
//...
15
}
Copied!

Mapping values to Interfaces

One of the most powerful parts about services is the ability to map a service to an interface. For instance, if you wanted to override the http.ResponseWriter with an object that wrapped it and performed extra operations, you can write the following handler:
1
func WrapResponseWriter(ctx *macaron.Context) {
2
rw := NewSpecialResponseWriter(ctx.Resp)
3
// override ResponseWriter with our wrapper ResponseWriter
4
ctx.MapTo(rw, (*http.ResponseWriter)(nil))
5
}
Copied!
In this way, your code can enjoy new custom service feature without any change. Plus, allow more custom implementations of same type of services.
Last modified 2yr ago