net/http
工具包;可是在实际项目中,团队仍是会选择更加高效,更便捷的Web框架,如Gin
、Echo
,Beego
等;Gin
这个框架,它在net/http
的基础上作了优化;对比其余主流框架,它更好的性能和更快的路由;快速:基于Radix
树的路由,性能很是强大。git
支持中间件:内置许多中间件,如Logger
,Gzip
,Authorization
等。github
崩溃恢复:能够捕捉panic引起的程序崩溃,使Web服务能够一直运行。web
JSON验证:能够验证请求中JSON
数据格式。api
路由分组:支持路由分组(RouteGroup
),能够更方便组织路由。数组
错误管理机制:能够收集程序中的错误bash
多种数据渲染方式:支持HTML
、JSON
、YAML
、XML
等数据格式的响应。服务器
扩展性:很是简单扩展中间件。数据结构
数据验证器:支持数据验证器且能够自定义。框架
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func setupRouter() *gin.Engine {
r := gin.Default()
// Ping test
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"status" : 0,
"msg" : "success",
"data" : gin.H {
"content" : "pong",
},
})
})
return r
}
func main() {
r := setupRouter()
r.Run()
}
复制代码
从Demo Code能够看出,使用Gin的体验很是顺滑,定义处理Web请求就四步:导入包、定义路由、编写 Handler、监听端口。函数
import "github.com/gin-gonic/gin"
复制代码
gin.Default()
方法建立并返回gin.Engine实例
.r := gin.Default() //r默认使用了Logger和Recovery两个中间件
复制代码
说明:能够用gin.New()
方法建立并返回一个不包含任何中间件的gin.Engine实例
经过默认路由,咱们能够建立处理HTTP请求的方法,示例中使用GET方法:
// Ping test
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"status" : 0,
"msg" : "success",
"data" : gin.H {
"content" : "pong",
},
})
})
复制代码
RouterGroup
的handle
方法, 请求的处理是使用HandlerFunc
类型方法// GET is a shortcut for router.Handle("GET", path, handle).
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
return group.handle("GET", relativePath, handlers)
}
// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context) 复制代码
GET
,POST
,PUT
,PATCH
,OPTIONS
,HEAD
,DELETE
。r.Run()
复制代码
http.ListenAndServe
,其中:http来自net/http
包。func (engine *Engine) Run(addr ...string) (err error) {
defer func() { debugPrintError(err) }()
address := resolveAddress(addr)
debugPrint("Listening and serving HTTP on %s\n", address)
//
err = http.ListenAndServe(address, engine)
return
}
复制代码
在Gin Simple Demo Code中,咱们发现了三个重要的Go数据结构:gin.Engine
、gin.Context
和 gin.RouterGroup
// Engine is the framework's instance, it contains the muxer, middleware and configuration settings.
// Create an instance of Engine, by using New() or Default()
type Engine struct {
RouterGroup
//....
}
复制代码
推荐使用
)。func Default() *Engine {
debugPrintWARNINGDefault()
engine := New()
engine.Use(Logger(), Recovery())
return engine
}
复制代码
gin.Context
的结构定义以下:// Context容许咱们在中间件之间传递变量,管理流程,验证请求的JSON,并返回JSON
type Context struct {
//请求对象
Request *http.Request
// 用来响应
writermem responseWriter
Writer ResponseWriter
// URL里面的参数,好比:/xx/:id
Params Params
// 参与的处理者(中间件 + 请求处理者列表)
handlers HandlersChain
// 当前处理到的handler的下标
index int8
fullPath string
// Engine单例
engine *Engine
// 在context能够设置的值
Keys map[string]interface{}
// 一系列的错误
Errors errorMsgs
//为内容协商定义一组手动接受的格式。
Accepted []string
// queryCache use url.ParseQuery cached the param query result from c.Request.URL.Query()
queryCache url.Values
// formCache use url.ParseQuery cached PostForm contains the parsed form data from POST, PATCH,
// or PUT body parameters.
formCache url.Values
}
复制代码
handleHTTPRequest
函数中。func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// 从对象池中获取一个context对象
c := engine.pool.Get().(*Context)
// 初始化上下文对象,由于从对象池取出来的数据,有脏数据,故要初始化。
c.writermem.reset(w)
c.Request = req
c.reset()
//处理web请求 (http请求处理)
engine.handleHTTPRequest(c)
//将Context对象扔回对象池了
engine.pool.Put(c)
}
复制代码
// RouterGroup is used internally to configure router, a RouterGroup is associated with
// a prefix and an array of handlers (middleware).
type RouterGroup struct {
Handlers HandlersChain
basePath string
engine *Engine
root bool
}
// HandlersChain defines a HandlerFunc array.
type HandlersChain []HandlerFunc
复制代码
RouteGroup 对象中主要包括:basePath
(前缀路径)、Engine 指针
和Handlers
(处理函数数组)。
RouterGroup 实现了 IRouter 接口定义的一系列路由方法;这些方法最终都是经过调用 Engine.addRoute 方法将请求处理器挂接到路由树中。
RouterGroup 内部有一个前缀路径属性,它会将全部的子路径都加上这个前缀再放进路由树中。有了这个前缀路径,就能够实现 URL 分组功能。Engine 对象内嵌的 RouterGroup 对象的前缀路径是 /,它表示根路径。RouterGroup 支持分组嵌套,使用 Group 方法就可让分组下面再挂分组。
v1 := r.Group("/api/v1")
{
v1.POST("/submit",submit)
v1.GET("/list",list)
}
// Engine对象中RouterGroup对象是第一层分组(根分组),v1是根分组的子分组。
复制代码
type H map[string]interface{}
复制代码