一个基于 go 语言开发 API 的工具,这个工具受到了 SpringMVC 的启发,结合了 go 语言本身的特性,整体比较简单,接下来,看看如何使用它。
下载安装:
- go get github.com / alberliu / goweb
- package main
- import "github.com/alberliu/goweb"
- type User struct {
- Id int `json:"id"`
- Name string `json:"name"`
- }
- func handler(user User) User {
- return user
- }
- func main() {
- goweb.HandlePost("/test", handler)
- goweb.ListenAndServe(":8000")
- }
请求体:
- {
- "id": 1,
- "name": "alber"
- }
响应体:
- {
- "id": 1,
- "name": "alber"
- }
上面的代码是一个最简的例子,HandlePost(string, interface{}) 会将一个 handler 注册到一个全局的内置的 goweb 实例 defultGoWeb,ListenAndServe(":8000") 会将 defultGoWeb 赋给 Server 的 handler 变量,然后启动这个 Server。(是不是和内置的 ServerMux 有点像)
goweb 会自动解析注册到它本身的 handler, 当请求到来时,会将请求体的 json 数据反序列化并注入到 handler 的参数,handler 处理完逻辑返回时,会将 handler 的返回值序列化为 json 数据返回。goweb 默认使用 json 的序列化和反序列化方式,当然你可以定义自己的序列化方式,这个在后面你可以看到。
例子给出的 handler 的参数和返回都是结构体类型,当然你也可以使用指针类型。
结构体 goweb 其实本质上就是一个路由,它实现了 Handler 接口。上面的例子都是默认的 defultGoWeb,你也可以自己实例化一个 goweb。
- func main() {
- goweb:=goweb.NewGoWeb();
- goweb.HandlePost("/test", handler)
- server := &http.Server{Addr: ":8000", Handler: goweb}
- server.ListenAndServe()
- }
- package main
- import "github.com/alberliu/goweb"
- type User struct {
- Id int64`json: "id"`Name string`json: "name"`
- }
- func handler(id int64, name string) User {
- return User {
- id,
- name
- }
- }
- func main() {
- goweb: =goweb.NewGoWeb();
- goweb.HandleGet("/test/{id}/{name}", handler) goweb.ListenAndServe(":8000")
- }
执行上面的代码,然后访问 url: http://localhost:8000/test/123456/alber
就可以返回下面的 json 数据
- {
- "id": 123456,
- "name": "alber"
- }
handler 可以获取到 url 中的参数,并且注入到 handler 参数中。handler 的第一个参数对应 url 中的第一个参数,第二个参数对应 url 中的的第二个参数,依次类推。不过暂时还有个限制,在 url 中使用参数时,handler 中的参数必须与 url 中的参数个数一致,且类型必须为 string 或者 int64。
goweb 可以注册多种形式的 handler,goweb 会利用反射自动解析函数,支持多种类型,但是不能超出它可以解析的范围。以下是它所有能解析的类型。
- func handler(ctx goweb.Context) {}
- func handler(ctx goweb.Context) User {
- return User {}
- }
- func handler(user User) User {
- return User {}
- }
- func handler(ctx goweb.Context, user User) User {
- return User {}
- }
- func handler(name string, id int64) User {
- return User {}
- }
- func handler(ctx goweb.Context, name string, id int64) User {
- return User {}
- }
Context 是一个请求上下文,他只有 ResponseWriter 和 Request 两个字段,它的内部结构如下所示。你可以根据自己的需求修改源码进行扩展,例如,把它作为一个请求的会话使用。
- type Context struct {
- w http.ResponseWriter
- r *http.Request
- }
- func main() {
- group1:=goweb.NewGroup("/group1")
- group1.HandleGet("/handler1",handler)
- group1.HandleGet("/handler2",handler)
- group1.HandleGet("/handler3",handler)
- group2:=goweb.NewGroup("/group2")
- group2.HandleGet("/handler1",handler)
- group2.HandleGet("/handler2",handler)
- group2.HandleGet("/handler3",handler)
- group3:=goweb.NewGroup("/group3")
- group3.HandleGet("/handler1",handler)
- group3.HandleGet("/handler2",handler)
- group3.HandleGet("/handler3",handler)
- goweb.HandleGroup(group1)
- goweb.HandleGroup(group2)
- goweb.HandleGroup(group3)
- goweb.ListenAndServe(":8000")
- }
group 可以帮助你分层次的组织你的 handler, 使你的路由结构更清晰。
- var json = jsoniter.ConfigCompatibleWithStandardLibrary
- func jsonUnmarshal(data[] byte, v interface {}) error {
- return json.Unmarshal(data, v)
- }
- func jsonMarshal(v interface {})([] byte, error) {
- return json.Marshal(v)
- }
- func main() {
- goweb: =goweb.NewGoWeb();
- goweb.Unmarshal = jsonUnmarshal goweb.Marshal = jsonMarshal
- goweb.ListenAndServe(":8000")
- }
goweb 默认采用 json(使用的是开源的 jsoniter) 序列化和反序列化数据,goweb 的 Marshal、Unmarshal 变量本身是一个函数. 如果你想定义自己的序列化方式,只需要覆盖掉它就行,就像上面那样。
- func interceptor1(http.ResponseWriter, *http.Request) bool {
- return true
- }
- func interceptor2(http.ResponseWriter, *http.Request) bool {
- return true
- }
- func interceptor3(http.ResponseWriter, *http.Request) bool {
- return true
- }
- func main() {
- goweb := goweb.NewGoWeb();
- goweb.AddInterceptor(interceptor1)
- goweb.AddInterceptor(interceptor2)
- goweb.AddInterceptor(interceptor3)
- goweb.ListenAndServe(":8000")
- }
goweb 在执行 handler 之前,会执行一个或者多个 interceptor,并且会根据 AddInterceptor 的先后顺序执行,当 interceptor 返回 true 时,会接着往下执行,返回 false 时,会终止执行。
- func filter(w http.ResponseWriter, r *http.Request, f func(http.ResponseWriter, *http.Request)) {
- f(w, r)
- }
- func main() {
- goweb := goweb.NewGoWeb();
- goweb.Filter = filter
- goweb.ListenAndServe(":8000")
- }
你可以给 goweb 添加一个过略器,在过滤器中,如果你想执行完自己的逻辑之后,执行 handler,只需要调用 f(w, r)。
- func handler400(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(400)
- w.Write([]byte("bad request"))
- }
- func handler404(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(404)
- w.Write([]byte("url not found"))
- }
- func handler405(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(405)
- w.Write([]byte("method not found"))
- }
- func main() {
- goWeb := goweb.NewGoWeb()
- goWeb.Handler400 = handler400
- goWeb.Handler404 = handler404
- goWeb.Handler405 = handler405
- goweb.ListenAndServe(":8000")
- }
当请求执行失败时,goweb 中给出了一些默认的错误处理方式,就像上面那样。当然,你也可以定义一些自己错误处理方式。
如果你有什么好的建议,可以发我邮箱,一起交流。
来源: https://juejin.im/entry/5a3765e351882512d822cfdf