Faygo 一款最适合开发 API 的 Go Web 框架
v10yjjngf
8年前
<h2>Faygo 框架</h2> <p>Faygo 使用全新架构,是最合适开发API接口的Go Web框架。用户只需定义一个struct Handler,就能自动绑定、验证请求参数并生成在线API文档。</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/fe0754a39ae3424edf1a29b9da0ea635.png"></p> <p>faygo index</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/b929670a681068ff48685f04e9c2ef7d.png"></p> <p>faygo apidoc</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/4924199ab7abd7cf10888b1eb497802c.png"></p> <p>faygo server</p> <h3>安装要求</h3> <p>Go Version ≥1.8</p> <h2>快速使用</h2> <ul> <li>方式一 源码下载</li> </ul> <pre> <code class="language-go">go get -u -v github.com/henrylee2cn/faygo</code></pre> <ul> <li>方式二 部署工具 ( Go to fay )</li> </ul> <pre> <code class="language-go">go get -u -v github.com/henrylee2cn/fay</code></pre> <pre> <code class="language-go">fay command [arguments] The commands are: new 创建、编译和运行(监控文件变化)一个新的faygo项目 run 编译和运行(监控文件变化)任意一个已存在的golang项目 fay new appname [apptpl] appname 指定新faygo项目的创建目录 apptpl 指定一个faygo项目模板(可选) fay run [appname] appname 指定待运行的golang项目路径(可选)</code></pre> <h2>框架特性</h2> <ul> <li> <p>一个 struct Handler 搞定多件事:</p> <ul> <li>定义 Handler/Middleware</li> <li>绑定与验证请求参数</li> <li>生成 Swagger2.0 API 在线文档</li> <li>数据库 ORM 映射</li> </ul> </li> <li> <p>Handler与Middleware完全相同,都是实现Handler接口( func 或 struct 类型),共同构成路由操作链,只是概念层面的说法不同</p> </li> <li>支持多种网络类型:</li> </ul> <table> <thead> <tr> <th>网络类型</th> <th>配置 net_types 值</th> </tr> </thead> <tbody> <tr> <td>HTTP</td> <td>http</td> </tr> <tr> <td>HTTPS/HTTP2(TLS)</td> <td>https</td> </tr> <tr> <td>HTTPS/HTTP2(Let's Encrypt TLS)</td> <td>letsencrypt</td> </tr> <tr> <td>HTTPS/HTTP2(Let's Encrypt TLS on UNIX socket)</td> <td>unix_letsencrypt</td> </tr> <tr> <td>HTTP(UNIX socket)</td> <td>unix_http</td> </tr> <tr> <td>HTTPS/HTTP2(TLS on UNIX socket)</td> <td>unix_https</td> </tr> </tbody> </table> <ul> <li>支持单服务单监听、单服务多监听、多服务多监听等,多个服务的配置信息相互独立</li> <li>基于 httprouter 开发高性能路由,支持链式与树形两种注册风格,支持灵活的静态文件路由(如DirFS、RenderFS、MarkdownFS等)</li> <li>支持平滑关闭、平滑升级,提供fay工具进行新建项目、热编译、元编程</li> <li>采用最强大的 pongo2 作为HTML渲染引擎</li> <li>提供近似LRU的文件缓存功能,主要用途是静态文件缓存</li> <li>跨平台的彩色日志系统,且同时支持console和file两种输出形式(可以同时使用)</li> <li>提供Session管理功能</li> <li>支持Gzip全局配置</li> <li>提供XSRF跨站请求伪造安全过滤</li> <li>大多数功能尽量使用简洁的ini进行配置来避免不必要的重新编译,并且这些配置文件支持自动补填默认值</li> <li>提供 gorm 、 xorm 、 sqlx 、 directSQL 、 Websocket 、 ini 、 http client 等很多常用扩展包</li> </ul> <p><img src="https://simg.open-open.com/show/a5ae7e231a8b4bbe53e61dfbbded7f08.png"></p> <p>faygo struct handler 多重用途合一</p> <h2>简单示例</h2> <pre> <code class="language-go">package main import ( // "mime/multipart" "time" "github.com/henrylee2cn/faygo" ) type Index struct { Id int `param:"<in:path> <required> <desc:ID> <range: 0:10>"` Title string `param:"<in:query> <nonzero>"` Paragraph []string `param:"<in:query> <name:p> <len: 1:10> <regexp: ^[\\w]*$>"` Cookie string `param:"<in:cookie> <name:faygoID>"` // Picture *multipart.FileHeader `param:"<in:formData> <name:pic> <maxmb:30>"` } func (i *Index) Serve(ctx *faygo.Context) error { if ctx.CookieParam("faygoID") == "" { ctx.SetCookie("faygoID", time.Now().String()) } return ctx.JSON(200, i) } func main() { app := faygo.New("myapp", "0.1") // Register the route in a chain style app.GET("/index/:id", new(Index)) // Register the route in a tree style // app.Route( // app.NewGET("/index/:id", new(Index)), // ) // Start the service faygo.Run() } /* http GET: http://localhost:8080/index/1?title=test&p=abc&p=xyz response: { "Id": 1, "Title": "test", "Paragraph": [ "abc", "xyz" ], "Cookie": "2016-11-13 01:14:40.9038005 +0800 CST" } */</code></pre> <h2>操作和中间件</h2> <p>操作和中间件是相同的,都是实现了Handler接口!</p> <ul> <li>函数类型</li> </ul> <pre> <code class="language-go">// 不含API文档描述 func Page() faygo.HandlerFunc { return func(ctx *faygo.Context) error { return ctx.String(200, "faygo") } } // 含API文档描述 var Page2 = faygo.WrapDoc(Page(), "测试页2的注意事项", "文本")</code></pre> <ul> <li>结构体类型</li> </ul> <pre> <code class="language-go">// Param操作通过Tag绑定并验证请求参数 type Param struct { Id int `param:"<in:path> <required> <desc:ID> <range: 0:10>"` Title string `param:"<in:query>"` } // Serve实现Handler接口 func (p *Param) Serve(ctx *faygo.Context) error { return ctx.JSON(200, faygo.Map{ "Struct Params": p, "Additional Param": ctx.PathParam("additional"), }, true) } // Doc实现API文档接口(可选) func (p *Param) Doc() faygo.Doc { return faygo.Doc{ // 向API文档声明接口注意事项 Note: "param desc", // 向API文档声明响应内容格式 Return: faygo.JSONMsg{ Code: 1, Info: "success", }, // 向API文档增加额外的请求参数声明(可选) Params: []faygo.ParamInfo{ { Name: "additional", In: "path", Model: "a", Desc: "defined by the `Doc()` method", }, }, } }</code></pre> <h2>过滤函数</h2> <p>过滤函数必须是HandlerFunc类型!</p> <pre> <code class="language-go">func Root2Index(ctx *faygo.Context) error { // 不允许直接访问`/index` if ctx.Path() == "/index" { ctx.Stop() return nil } if ctx.Path() == "/" { ctx.ModifyPath("/index") } return nil }</code></pre> <h2>路由注册</h2> <ul> <li>树状</li> </ul> <pre> <code class="language-go">// 新建应用服务,参数:名称、版本 var app1 = faygo.New("myapp1", "1.0") // 路由 app1.Filter(Root2Index). Route( app1.NewNamedGET("测试页1", "/page", Page()), app1.NewNamedGET("测试页2", "/page2", Page2), app1.NewGroup("home", app1.NewNamedGET("test param", "/param", &Param{ // 为绑定的参数设定API文档中缺省值(可选) Id: 1, Title: "test param", }), ), )</code></pre> <ul> <li>链状</li> </ul> <pre> <code class="language-go">// 新建应用服务,参数:名称、版本 var app2 = faygo.New("myapp2", "1.0") // 路由 app2.Filter(Root2Index) app2.NamedGET("test page", "/page", Page()) app2.NamedGET("test page2", "/page2", Page2) app2.Group("home") { app2.NamedGET("test param", "/param", &Param{ // 为绑定的参数设定API文档中缺省值(可选) Id: 1, Title: "test param", }) }</code></pre> <h2>平滑关闭与重启</h2> <ul> <li>平滑关闭</li> </ul> <pre> <code class="language-go">kill [pid]</code></pre> <ul> <li>平滑重启</li> </ul> <pre> <code class="language-go">kill -USR2 [pid]</code></pre> <h2>扩展包</h2> <table> <thead> <tr> <th>扩展包</th> <th>导入路径</th> </tr> </thead> <tbody> <tr> <td><a href="/misc/goto?guid=4959739068293079600" rel="nofollow,noindex">各种条码</a></td> <td>github.com/henrylee2cn/faygo/ext/barcode</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739068382826658" rel="nofollow,noindex">比特单位</a></td> <td>github.com/henrylee2cn/faygo/ext/bitconv</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739068472668811" rel="nofollow,noindex">gorm数据库引擎</a></td> <td>github.com/henrylee2cn/faygo/ext/db/gorm</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739068555973865" rel="nofollow,noindex">sqlx数据库引擎</a></td> <td>github.com/henrylee2cn/faygo/ext/db/sqlx</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739068626771553" rel="nofollow,noindex">xorm数据库引擎</a></td> <td>github.com/henrylee2cn/faygo/ext/db/xorm</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739068720017584" rel="nofollow,noindex">directSQL(配置化SQL引擎)</a></td> <td>github.com/henrylee2cn/faygo/ext/db/directsql</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739068795853812" rel="nofollow,noindex">口令算法</a></td> <td>github.com/henrylee2cn/faygo/ext/otp</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739068876853617" rel="nofollow,noindex">UUID</a></td> <td>github.com/henrylee2cn/faygo/ext/uuid</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739068968277296" rel="nofollow,noindex">Websocket</a></td> <td>github.com/henrylee2cn/faygo/ext/websocket</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739069052816079" rel="nofollow,noindex">ini配置</a></td> <td>github.com/henrylee2cn/faygo/ini</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739069137895239" rel="nofollow,noindex">定时器</a></td> <td>github.com/henrylee2cn/faygo/ext/cron</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739069221244976" rel="nofollow,noindex">任务工具</a></td> <td>github.com/henrylee2cn/faygo/ext/task</td> </tr> <tr> <td><a href="/misc/goto?guid=4959739069298148596" rel="nofollow,noindex">HTTP客户端</a></td> <td>github.com/henrylee2cn/faygo/ext/surfer</td> </tr> </tbody> </table> <h2>开源协议</h2> <p>Faygo 项目采用商业应用友好的 <a href="/misc/goto?guid=4959739069386501256" rel="nofollow,noindex">Apache2.0</a> 协议发布。</p> <p> </p> <p>来自:http://www.jianshu.com/p/f40b65ccf7a5</p> <p> </p>