Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
53 lines (41 sloc) 1.76 KB

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:

db := &MyDatabase{}
m := macaron.Classic()
m.Map(db) // Service will be available to all handlers as *MyDatabase
m.Get("/", func(db *MyDatabase) {
	// Operations with db.

Request-Level Mapping

Mapping on the request level can be done in a handler via *macaron.Context:

func MyCustomLoggerHandler(ctx *macaron.Context) {
	logger := &MyCustomLogger{ctx.Req}
	ctx.Map(logger) // mapped as *MyCustomLogger

func main() {
	m.Get("/", MyCustomLoggerHandler, func(logger *MyCustomLogger) {
		// Operations with logger.
	m.Get("/panic", func(logger *MyCustomLogger) {
		// This will panic because no logger service maps to this request.

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:

func WrapResponseWriter(ctx *macaron.Context) {
	rw := NewSpecialResponseWriter(ctx.Resp)
	// override ResponseWriter with our wrapper ResponseWriter
	ctx.MapTo(rw, (*http.ResponseWriter)(nil)) 

In this way, your code can enjoy new custom service feature without any change. Plus, allow more custom implementations of same type of services.

You can’t perform that action at this time.