已知的其余框架看到的是传统OOP的影子, 处处充蚀 Class 风格的 OOP 方法. 而咱们知道GoLang中是没有Class的. 笔者也曾努力用Go 的风格作WEB开发, 总感到力不从心. 写出的代码不能彻底称之为框架, 到更像一个拷贝源码使用的应用. 要达到灵活须要修改源码. 直到看到了 Martini. 纯 GoLang 风格的框架出现了.git
Injector 是 Martini 的核心. 其代码很是简洁. 功能仅仅是经过反射包, 对函数进行参数类型自动匹配进行调用. 笔者曾经为完成相似的功能写了typeless, 这是一个繁琐的高成本的实验品. Injector 把事情简单化了, Injector 假设函数的参数都具备不一样的类型. 在WEB开发中的 HandlerFunc 一般都具备这样的形式. 所以经过反射包能够对参数进行自动的匹配并调用HandlerFunc, 固然事先要把全部可能使用到的参数 Map/MapTo 给 Injector 对象, 这很容易并且是能够预见的.github
Martini的路由 router.go 写的很是简洁实用, 可见做者使用正则的功力很是深厚. 举例:web
"/wap/:category/pow/**/:id"数据库
匹配: "/wap/Golang/pow/Path1/ToPathN/Foo"app
这里的中间件泛指应用需求中的流程控制, 预处理, 过滤器, 捕获 panic, 日志等等.这些依然是Injector在背后提供动力.框架
举例源代码中的 ClassicMartini ,固然你能够按需求模仿一个.less
<!-- lang: cpp --> func Classic() *ClassicMartini { r := NewRouter() m := New() // m.Use(Logger()) // 启用日志 m.Use(Recovery()) // 捕获 panic m.Use(Static("public")) // 静态文件 m.Action(r.Handle) // 最后一个实际上是执行了默认的路由机制 return &ClassicMartini{m, r} }
其中 Recovery() 和 func (r *routeContext) run() 配合的方法很是值得读一下, 一个简单的计数器就完成了.函数
martini-contrib 中的 web 包展现了如何经过 Martini.Use 接口进行中间件的设计. 加入新的 HandlerFunc 参数类型就是经过 Map 完成的.ui
假如咱们要完成对 Response 流程的控制, 达不到某个条件中断 Use 和 Action 设置的Handler. 那能够简单的经过 Use 加入本身的 Recovery 和判断 Handler 实现debug
<!-- lang: cpp --> func Recovery() Handler { return func(res http.ResponseWriter, c Context, logger *log.Logger) { defer func() { if err := recover(); err != nil { s, ok := err.(string) // 示意用 string,你能够定义类型 if ok && s == "dont ServerError" { return } res.WriteHeader(http.StatusInternalServerError) logger.Printf("PANIC: %s\n%s", err, debug.Stack()) } }() c.Next() } } func MyHandler() Handler { return func(req *http.Request) { if something { panic("dont ServerError") } } } m.Use(Recovery()) m.Use(MyHandler())
甚至
<!-- lang: cpp --> // 支持 Handlers 返回值输出 m.Get("/", func() string { return "hello world" // HTTP 200 : "hello world" }) // 向 handlers 传递数据库对象 db := &MyDatabase{} m := martini.Classic() m.Map(db) // the service will be available to all handlers as *MyDatabase // ... m.Run()
变化和自由度很是高. 正如 Martini 介绍的:
Martini is a powerful package for quickly writing modular web applications/services in Golang.
martini是一个极好的web框架,使人惊讶的简单,不可思议的高效。
是的, 这才是真正的 GoLang 风格.
开发者创建了 martini-contrib 组织. 这样的管理方式更开放. 事实上这样符合 Martini Injector 的风格, 组件之间的依赖能够经过 Injector 的 Map/Invoke 机制完成.