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{}
複製代碼