I. Обзор
1. Введение
- Для поддержки веб-разработки Go официально предоставляет
net/http
Toolkit, но в реальных проектах команда все равно выберет более эффективный и удобный веб-фреймворк, напримерGin
,Echo
,Beego
Ждать; - Среди этих команд многие команды выбрали
Gin
эта структура, она находится вnet/http
Оптимизирован на основе; по сравнению с другими основными фреймворками, онлучшая производительностьа такжеболее быстрая маршрутизация;
2. Преимущества джина
-
быстро: на основе
Radix
Производительность маршрутизации по дереву очень высока. -
Поддержка промежуточного программного обеспечения: существует множество встроенных промежуточного программного обеспечения, таких как
Logger
,Gzip
,Authorization
Ждать. -
Восстановление после сбоя: сбой программы, вызванный паникой, может быть обнаружен, чтобы веб-служба всегда могла работать.
-
Проверка JSON: можно проверить запрос
JSON
Формат данных. -
Группировка маршрутизации: поддерживает группировку маршрутизации (
RouteGroup
), что упрощает организацию маршрутов. -
Механизм управления ошибками: может собирать ошибки в программе
-
Несколько методов рендеринга данных: поддержка
HTML
,JSON
,YAML
,XML
и другие ответы формата данных. -
Расширяемость: промежуточное ПО очень легко расширяется.
-
Средство проверки данных: средство проверки данных поддерживается и может быть настроено.
3. Простая демонстрация джина
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()
}
2. Интерпретация демо-версии Gin Simple
Как видно из демо-кода, опыт использования Gin очень гладкий.Есть четыре шага для определения и обработки веб-запросов:импортный пакет,определить маршруты,обработчик записи,порт прослушивания.
1. Импортируйте пакет
import "github.com/gin-gonic/gin"
2. Определите маршрут
- gin.engine - это двигатель маршрутизации, обычно используется
gin.Default()
метод создает и возвращаетgin.Engine实例
.
r := gin.Default() //r默认使用了Logger和Recovery两个中间件
иллюстрировать:Можно использоватьgin.New()
метод создает и возвращаетgin.Engine实例
3. Написать обработчик
С маршрутом по умолчанию мы можем создавать методы для обработки 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",
},
})
})
- Базовая реализация метода Get заключается в вызове
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)
- Описание: Gin поддерживает все распространенные методы HTTP-запросов, такие как
GET
,POST
,PUT
,PATCH
,OPTIONS
,HEAD
,DELETE
.
4. Порт прослушивания
- После определения запроса используйте метод Run() для прослушивания порта и начала приема HTTP-запросов.Если метод Run() не передает параметры, он по умолчанию будет прослушивать порт 8080.
r.Run()
- Ключ к базовой реализации метода 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
}
3. Важные структуры данных в Gin
В простом демонстрационном коде Gin мы обнаружили три важные структуры данных Go:gin.Engine
,gin.Context
а такжеgin.RouterGroup
1. Джин.Двигатель
- gin.Engine — это точка входа в структуру; мы используем объект Engine для определения информации о маршрутизации службы, сборки подключаемых модулей и запуска служб, и весь веб-сервис управляется им.
// 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
//....
}
- gin.Engine по сути представляет собой оболочку встроенного HTTP-сервера, что делает его более удобным в использовании.
- Функция gin.Default () создаст объект Engine по умолчанию, который содержит два общих плагина по умолчанию, а именно Logger и Recovery. Logger используется для вывода журналов запросов. Recovery гарантирует, что при панике одного запроса журнал стека исключений записывается и вывод унифицированного ответа на ошибку (
推荐使用
).
func Default() *Engine {
debugPrintWARNINGDefault()
engine := New()
engine.Use(Logger(), Recovery())
return engine
}
- Функция gin.New() создаст объект Engine по умолчанию, который не содержит экземпляров промежуточного программного обеспечения gin.Engine.
2. Джин.Контекст
- Информационный объект контекста запроса, который является входным параметром всех обработчиков запросов.
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
}
- Объект контекста Context не генерируется каждый раз, а вынимается из пула объектов, а реальное ядро обработки запроса находится в
handleHTTPRequest
в функции. - Основная логика в функции handleHTTPRequest: в соответствии с методом запроса и запрошенным URI найти и вызвать обработанныймассив функций(Включая функцию обработки, которую мы определены, а также функция обработки среднего слоя).
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)
}
3. джин.Группа маршрутизаторов
- RouterGroup — это группа маршрутизации, представляющая собой упаковку дерева маршрутизации, и все правила маршрутизации в конечном итоге управляются ею. Структура Engine наследует RouterGroup, поэтому Engine напрямую имеет все функции управления маршрутизацией от RouterGroup.
// 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-адресов. Префикс пути объекта RouterGroup, встроенного в объект Engine, — это /, который представляет корневой путь. RouterGroup поддерживает вложенность групп.Используя метод Group, группу можно связать ниже группы.
v1 := r.Group("/api/v1") { v1.POST("/submit",submit) v1.GET("/list",list) } // Engine对象中RouterGroup对象是第一层分组(根分组),v1是根分组的子分组。
4. джин.ч
- gin.H — это сокращенное имя для map[string]interface{}.
type H map[string]interface{}