Go Web Lightweight Framework Gin Learning Series: привязка данных

Go

Оригинальный автор, публичный аккаунт [программист чтение], прошу обратить внимание на паблик-аккаунт, просьба указывать источник перепечатываемой статьи.

Я написал две статьи ранее иGinСтатьи, связанные с фреймворком обучения, в основном оGinУстановка фреймворка, обработка определенийHTTPРазличные методы запроса и способы возврата данных в разных форматах в соответствии с требованиями клиента, но в середине отсутствует звено, то есть как получить клиента перед возвратом данныхHTTPКакие параметры заносятся в запрос, об этом мы и поговорим в этой статье.

Ginфреймворк справитсяHTTPТакие операции, как параметры запроса и способ ответа, инкапсулированы вgin.Conetxtструктура и являетсяgin.ContextЕсть так много доступных методов, так что поймитеgin.ContextОпределения структуры и методыGinрамочное письмоWebПроекты очень важны.

Нижеgin.ContextКод определения структуры:

type Context struct {
    Request *http.Request
    Writer  ResponseWriter
    Params Params
    // Keys is a key/value pair exclusively for the context of each request.
    Keys map[string]interface{}
    // Errors is a list of errors attached to all the handlers/middlewares who used this context.
    Errors errorMsgs
    // Accepted defines a list of manually accepted formats for content negotiation.
    Accepted []string
    // contains filtered or unexported fields
}

сверхуgin.ContextИз структурного определения ,gin.Contextв упаковкеhttp.Requestиhttp.ResponseWriter

Получить параметры запроса

1. Path

путь относится к части, начинающейся с/после доменного имени в запрошенном URL-адресе, например адрес домашней страницы Nuggets:https://juejin.im/timeline,/timelineЧасть — это путь, вы можете использовать метод Param() в gin.Context, чтобы получить эту часть параметров.

func (c *Context) Param(key string) string

Используйте метод Param() для получения параметров в пути:

r.GET("/user/:id",func(c *gin.Context){
    id := c.Param("id")
})

В дополнение к использованию метода Param() в gin.Context вы также можете использовать поле Params в gin.Context для получения параметров в пути.Определение Params выглядит следующим образом:

type Params []Param
func (ps Params) ByName(name string) (va string)
func (ps Params) Get(name string) (string, bool)

Пример использования поля Params в gin.Context для получения параметров пути выглядит следующим образом:

r.GET("/user/:id",func(c *gin.Context){
    id,err := c.Params.Get("id")
    //id := c.Params.ByName("id")
})

2. Query

запрос относится к части после вопросительного знака в адресе запроса URL, называемой параметром запроса, как в следующем адресе,query=%E6%96%87%E7%AB%A0&type=allявляются параметрами запроса.

https://juejin.im/search?query=%E6%96%87%E7%AB%A0&type=all

gin.ContextДля получения параметров части запроса предусмотрены следующие методы.

1. Получить один параметр
func (c *Context) GetQuery(key string) (string, bool)
func (c *Context) Query(key string) string
func (c *Context) DefaultQuery(key, defaultValue string) string

Вышеупомянутые три метода используются для получения одного значения,GetQueryСравниватьQueryВозвращает еще один параметр типа error, по сутиQueryметод просто инкапсулируетGetQueryметод и игнорироватьGetQueryМетод возвращает ошибку, а метод DefaultQuery возвращает значение по умолчанию, если соответствующее значение параметра не получено.

Пример выглядит следующим образом:

r.GET("/user", func(c *gin.Context) {
    id,_ := c.GetQuery("id")
    //id := c.Query("id")
    //id := c.DefaultQuery("id","10")
    c.JSON(200,id)
})

просить:http://localhost:8080/user?id=11

отклик:11

2. Получить массив

Разница между методом GetQueryArray и QueryArray такая же, как у GetQuery и Query.

func (c *Context) GetQueryArray(key string) ([]string, bool)
func (c *Context) QueryArray(key string) []string

Пример выглядит следующим образом:

r.GET("/user", func(c *gin.Context) {
    ids := c.QueryArray("id")
    //id,_ := c.QueryArray("id")
    c.JSON(200,ids)
})

просить:http://localhost:8080/user?id=10&id=11&id=12

отклик:["10","11","12"]

3. Получить карту

Разница между методом GetQueryArray и QueryArray такая же, как у GetQuery и Query.

func (c *Context) QueryMap(key string) map[string]string
func (c *Context) GetQueryMap(key string) (map[string]string, bool)

Пример выглядит следующим образом:

r.GET("/user", func(c *gin.Context) {
    ids := c.QueryMap("ids")
    //ids,_ := c.GetQueryMap("ids")
    c.JSON(200,ids)
})

просить:http://localhost:8080/user?ids[10]=zhang

отклик:{"10":"zhang"}

3. Body

Как правило, параметры запроса HTTP Post передаются на сервер через часть тела, особенно данные с большим объемом данных или высокими требованиями к безопасности, такие как пароль учетной записи и другие параметры в функции входа в систему.

gin.Context предоставляет нам следующие четыре метода для получения данных в теле, но следует отметить, что следующие четыре метода могут быть получены толькоContent-typeдаapplication/x-www-form-urlencodedилиmultipart/form-dataВремяbodyданные в .

Использование следующего метода такое же, как тип использования метода для получения запроса выше. Разница заключается только в источнике данных. Образец программы здесь не будет написан.

func (c *Context) PostForm(key string) string
func (c *Context) PostFormArray(key string) []string
func (c *Context) PostFormMap(key string) map[string]string
func (c *Context) DefaultPostForm(key, defaultValue string) string
func (c *Context) GetPostForm(key string) (string, bool)
func (c *Context) GetPostFormArray(key string) ([]string, bool)
func (c *Context) GetPostFormMap(key string) (map[string]string, bool)
func (c *Context) GetRawData() ([]byte, error)

привязка данных

В предыдущем примере мы напрямую использовалиgin.ContextПредоставленный метод передается в запросеpath,query,bodyПараметры выставлены, но предыдущие методы не могут обрабатывать более сложные структуры данных в запросе.Например, когда Content-type имеет значение application/json или application/xml, данные, которые он приносит, будут очень сложными, поэтому нам нужно Используйте другой метод для получения этих данных, этот метод называется数据绑定.

GinПлатформа инкапсулирует операции привязки данных в пакете gin/binding.gin/binding包Определенные константы, заявляющиеgin/bindingпакет поддерживаетсяContent-typeФормат.

const (
    MIMEJSON              = "application/json"
    MIMEHTML              = "text/html"
    MIMEXML               = "application/xml"
    MIMEXML2              = "text/xml"
    MIMEPlain             = "text/plain"
    MIMEPOSTForm          = "application/x-www-form-urlencoded"
    MIMEMultipartPOSTForm = "multipart/form-data"
    MIMEPROTOBUF          = "application/x-protobuf"
    MIMEMSGPACK           = "application/x-msgpack"
    MIMEMSGPACK2          = "application/msgpack"
    MIMEYAML              = "application/x-yaml"
)

gin.bindingПакеты также определены для обработки различныхContent-typeСтруктура обработки, которая отправляет данные и делает их доступными для других пакетов в виде переменных, выглядит следующим образом:

var (
    JSON          = jsonBinding{}
    XML           = xmlBinding{}
    Form          = formBinding{}
    Query         = queryBinding{}
    FormPost      = formPostBinding{}
    FormMultipart = formMultipartBinding{}
    ProtoBuf      = protobufBinding{}
    MsgPack       = msgpackBinding{}
    YAML          = yamlBinding{}
    Uri           = uriBinding{}
)

Но на самом деле нам не нужно звонитьgin/bindingкод пакета для завершения функции привязки данных, потому чтоgin.Contextуже вgin.ContextНа основе инкапсуляции множества более быстрых методов, которые мы можем использовать:

gin.ContextСвязанные методы связывания инкапсуляции делятся наBindМетоды серии с префиксомShouldBindРазница между этими двумя сериями методов заключается в том, что метод с префиксом Bind будет напрямую возвращать клиенту ответ с HTTP-статусом 400, когда вводимые пользователем данные не соответствуют соответствующему формату.

Серия методов с префиксом Bind

1. Path
func (c *Context) BindUri(obj interface{}) error

Пример кода:

type User struct {
    Uid      int    //用户id
    Username string //用户名
}
func main() {
    r := gin.Default()
    r.GET("/bind/:uid/username", func(c *gin.Context) {
        var u User
        e := c.BindUri(&u)
        if e == nil{
            c.JSON(200,u)
        }
    })
    r.Run()
}

просить:http://localhost:8080/bind/1/小张

входить:{1,"小张"}

2. Query
func (c *Context) BindQuery(obj interface{}) error

Пример кода:

r.GET("/bind/:uid/username", func(c *gin.Context) {
    var u User
    e := c.BindQuery(&u)
    if e == nil{
        c.JSON(200,u)
    }
})

просить:http://localhost:8080/bind?uid=1&username=小张

вывод:{1,"小张"}

3. Body

когда мыHTTPпросьбаBodyЧтобы установить разные форматы данных, вам нужно установить соответствующий заголовокContent-TypeЗначение , чаще используемое какjson,xml,yaml,gin.ContextПредоставьте следующие три метода для привязки данных в теле, соответствующих Content-type.

func (c *Context) BindJSON(obj interface{}) error
func (c *Context) BindXML(obj interface{}) error
func (c *Context) BindYAML(obj interface{}) error

В дополнение к трем вышеупомянутым методам, более часто используемый метод Bind(), метод Bind() автоматически выбирает различные типы привязки в соответствии со значением Content-Type.

func (c *Context) Bind(obj interface{}) error

Пример

r.POST("bind",func(c *gin.Context){
    u := User{}
    c.Bind(&u)
})

Вышеупомянутые методы предназначены для получения фиксированного типа содержимого или автоматического выбора типа привязки в соответствии с типом содержимого.Мы также можем использовать следующие два метода для самостоятельного выбора типа привязки.

Вторым значением параметра следующих двух методов является константа, определенная в gin.binding, о которой мы говорили выше.

func (c *Context) BindWith(obj interface{}, b binding.Binding) error
func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error

Пример

r.POST("bind",func(c *gin.Context){
	u := User{}
	c.BindWith(&u,binding.JSON)
    c.MustBindWith(&u,binding.JSON)
})

Серия методов с префиксом ShouldBind

Соответствующий метод с префиксом ShouldBind в основном совпадает с методом с префиксом Bind, поэтому ниже нет соответствующего демонстрационного кода.

1. Path
func (c *Context) ShouldBindUri(obj interface{}) error
2. Query
func (c *Context) ShouldBindQuery(obj interface{}) error
3. Body
func (c *Context) ShouldBind(obj interface{}) error
func (c *Context) ShouldBindJSON(obj interface{}) error
func (c *Context) ShouldBindXML(obj interface{}) error
func (c *Context) ShouldBindYAML(obj interface{}) error
func (c *Context) ShouldBindBodyWith(obj interface{}, bb binding.BindingBody) (err error)
func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error

резюме

Ginкадр вnet/httpНа основе пакета инкапсулировано множество методов, так что мы можем получать данные в различных форматах от клиента, но после получения данных от клиента нам все равно нужно проверить, легальны ли данные или то, что мы хотим. являетсяGinВ рамках数据验证器знания, и иметь возможность писать статьи по этому поводу.


Ваше внимание — самое большое поощрение на моем писательском пути!