06使用 Go 读写请求

作者: 刷漆猫咪 | 来源:发表于2019-10-26 09:04 被阅读0次

简介

使用 web 框架, 最基础的事情就是读写请求了,
Gin 支持很多种类的请求参数, 也支持多种格式的响应.

读取请求参数

path 中的参数

使用 Param() 可以获取 path 中的参数.

定义在 path 中的参数有两种格式, 一个是 :name 的以冒号开头的,
另一种是 *action 的以星号开头的.

:name 是必定匹配的, 一定要有值, 不能为空. 下面的代码中, 第一个例子就是如此,
:name 来表示用户的名字, 这样就可以在路径中表示任意的用户名了.

*action 是可选的, 如果不存在, 就会忽略掉, 比如是可以匹配到 /user/john/ 的,
另外 /user/john 会被跳转到 /user/john/.

// This handler will match /user/john but will not match /user/ or /user
router.GET("/user/:name", func(c *gin.Context) {
  name := c.Param("name")
  c.String(http.StatusOK, "Hello %s", name)
})

// However, this one will match /user/john/ and also /user/john/send
// If no other routers match /user/john, it will redirect to /user/john/
router.GET("/user/:name/*action", func(c *gin.Context) {
  name := c.Param("name")
  action := c.Param("action")
  message := name + " is " + action
  c.String(http.StatusOK, message)
})

query 中的参数

使用 Query()DefaultQuery() 可以获取 query 中的参数,
后者使用第二个参数作为默认值.

// Query string parameters are parsed using the existing underlying request object.
// The request responds to a url matching:  /welcome?firstname=Jane&lastname=Doe
router.GET("/welcome", func(c *gin.Context) {
  firstname := c.DefaultQuery("firstname", "Guest")
  lastname := c.Query("lastname") // shortcut for c.Request.URL.Query().Get("lastname")

  c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
})

from 中的参数

对于 form (表单) 中的参数, 也有和 query 类似的方法, PostFormDefaultPostForm.

router.POST("/form_post", func(c *gin.Context) {
  message := c.PostForm("message")
  nick := c.DefaultPostForm("nick", "anonymous")

  c.JSON(200, gin.H{
    "status":  "posted",
    "message": message,
    "nick":    nick,
  })
})

模型绑定

上面的几种获取参数的方式都比较常规, 我觉得最有用的就是 模型绑定 了.

模型绑定首先要定义一个结构体 struct, struct 需要设置相应的 tag, 就是那些在反引号 ` 里面的字段,
然后就可以用对应的数据填充这个 struct 了, 也就是绑定.

// 绑定 JSON
type Login struct {
    User     string `form:"user" json:"user" xml:"user"  binding:"required"`
    Password string `form:"password" json:"password" xml:"password" binding:"required"`
}

// 绑定 JSON ({"user": "manu", "password": "123"})
router.POST("/loginJSON", func(c *gin.Context) {
  var json Login
  if err := c.ShouldBindJSON(&json); err != nil {
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    return
  }

  if json.User != "manu" || json.Password != "123" {
    c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
    return
  }

  c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
})

// 绑定 XML (
//  <?xml version="1.0" encoding="UTF-8"?>
//  <root>
//      <user>user</user>
//      <password>123</password>
//  </root>)
router.POST("/loginXML", func(c *gin.Context) {
  var xml Login
  if err := c.ShouldBindXML(&xml); err != nil {
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    return
  }

  if xml.User != "manu" || xml.Password != "123" {
    c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
    return
  }

  c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
})

// 绑定 HTML 表单 (user=manu&password=123)
router.POST("/loginForm", func(c *gin.Context) {
  var form Login
  // 根据 Content-Type Header 推断使用哪个绑定器。
  if err := c.ShouldBind(&form); err != nil {
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    return
  }

  if form.User != "manu" || form.Password != "123" {
    c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
    return
  }

  c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
})

上面的代码显示了三种不同的绑定, 分别是绑定 JSON 格式的请求体, XML 格式的请求体和普通的表单.

对于 query 也是使用 form tag 进行标记.

另外也可以绑定 Header (使用 header tag) 和 Uri (使用 uri tag) 等.

返回响应

对于请求, 也有多种类型的数据响应格式, 支持 XML, JSON, YAML 和 ProtoBuf.

func main() {
    r := gin.Default()

    // gin.H is a shortcut for map[string]interface{}
    r.GET("/someJSON", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
    })

    r.GET("/moreJSON", func(c *gin.Context) {
        // You also can use a struct
        var msg struct {
            Name    string `json:"user"`
            Message string
            Number  int
        }
        msg.Name = "Lena"
        msg.Message = "hey"
        msg.Number = 123
        // Note that msg.Name becomes "user" in the JSON
        // Will output  :   {"user": "Lena", "Message": "hey", "Number": 123}
        c.JSON(http.StatusOK, msg)
    })

    r.GET("/someXML", func(c *gin.Context) {
        c.XML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
    })

    r.GET("/someYAML", func(c *gin.Context) {
        c.YAML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
    })

    r.GET("/someProtoBuf", func(c *gin.Context) {
        reps := []int64{int64(1), int64(2)}
        label := "test"
        // The specific definition of protobuf is written in the testdata/protoexample file.
        data := &protoexample.Test{
            Label: &label,
            Reps:  reps,
        }
        // Note that data becomes binary data in the response
        // Will output protoexample.Test protobuf serialized data
        c.ProtoBuf(http.StatusOK, data)
    })

    // Listen and serve on 0.0.0.0:8080
    r.Run(":8080")
}

对于 API 服务来说, 这些已经足够用了, 主要还是用 JSON 格式的输出.
如果需要高性能, 可以使用 ProtoBuf, 但这不是人类易读的, 所以通常
来说 JSON 足以满足要求.

总结

主要介绍了如何使用 Gin 读取请求, 并返回响应.
这部分是 web 框架的基础, 框架的好用与否很大程度上
取决于这部分.

当前部分的代码

作为版本 v0.6.0

相关文章

  • 06使用 Go 读写请求

    简介 读取请求参数path 中的参数query 中的参数from 中的参数模型绑定 返回响应 总结 当前部分的代码...

  • 第05天(异常、文本文件处理)_04

    15_设备文件的使用.go 16_文件的读写.go 17_拷贝文件.go 课堂笔记

  • 用Go语言构建自己的区块链

    date[2019-01-06] 注意:当main包里面有多个go文件时,使用go build *.go运行,当然...

  • Go: 使用PUT发送Form Data

    我使用Go实现了一个PUT接口,在浏览器中可以使用ajax发送请求: 但是使用Go写test时,发送的请求却接收不...

  • 利用Go net/http发送Restful请求

    最近工作中涉及到了使用Go来发送restful请求,因为Go默认的http只提供GO&PATCH两种请求,其余类型...

  • Grequests 库的使用

    Golang:Grequests 库的使用 Go 语言版本的 request Go 语言内置的请求库 net/ht...

  • 第03天(复合类型)_02

    06_为什么需要数组.go 07_数组的基本使用.go 08_数组的初始化.go 09_二维数组的介绍.go 10...

  • 实战:异步爬取之异步的简单使用

    一、使用异步的注意事项 异步代码中不能有耗时的 I/O操作,像文件读写、网络请求、数据库读写等操作都需要使用对应的...

  • 跟踪IO请求

    1 目的 跟踪IO请求,分析磁盘读写性能瓶颈 2 工具 2.1 磁盘 geometry 2.2 读写请求 打开裸块...

  • Database Go and JSON

    在使用Go开发web项目的过程中, 数据库读写操作与JSON格式的输入输出是两块最基础的模块, Go的标准库已经帮...

网友评论

    本文标题:06使用 Go 读写请求

    本文链接:https://www.haomeiwen.com/subject/mswqvctx.html