Gin框架系列02:路由与参数

栏目: IT技术 · 发布时间: 4年前

内容简介:上一节我们用Gin框架快速搭建了一个GET请求的接口,今天来学习路由和参数的获取。熟悉同样的,Gin框架给我们提供的除这4种动词外,还有

回顾

上一节我们用Gin框架快速搭建了一个GET请求的接口,今天来学习路由和参数的获取。

请求动词

熟悉 RESTful 的同学应该知道, RESTful 是网络应用程序的一种设计风格和开发方式,每一个URI代表一种资源,客户端通过 POSTDELETEPUTGET 四种请求方式来对资源做增删改查的操作。

同样的,Gin框架给我们提供的除这4种动词外,还有 PATCHOPTIONHEAD 等,详细内容可以查看 rentergroup.go 文件的 IRoutes 接口。

type IRoutes interface {
    Use(...HandlerFunc) IRoutes

    Handle(string, string, ...HandlerFunc) IRoutes
    Any(string, ...HandlerFunc) IRoutes
    GET(string, ...HandlerFunc) IRoutes
    POST(string, ...HandlerFunc) IRoutes
    DELETE(string, ...HandlerFunc) IRoutes
    PATCH(string, ...HandlerFunc) IRoutes
    PUT(string, ...HandlerFunc) IRoutes
    OPTIONS(string, ...HandlerFunc) IRoutes
    HEAD(string, ...HandlerFunc) IRoutes

    StaticFile(string, string) IRoutes
    Static(string, string) IRoutes
    StaticFS(string, http.FileSystem) IRoutes
}

因为 RenterGroup 实现了 IRoutes 定义的所有请求动词,而且 gin.Default 返回的 Engine 类型继承了 RenterGroup ,所以使用起来非常简单,只需要通过 gin.Default 实例化对象,接下来所有的路由操作都通过该对象使用即可。

Gin框架系列02:路由与参数

func main() {
    router := gin.Default()
    router.POST("/article", func(c *gin.Context) {
        c.String(200, "article post")
    })
    router.DELETE("/article", func(c *gin.Context) {
        c.String(200, "article delete")
    })
    router.PUT("/article", func(c *gin.Context) {
        c.String(200, "article put")
    })
    router.GET("/article", func(c *gin.Context) {
        c.String(200, "article get")
    })
    router.Run()
}

请求动词的第一个参数是请求路径,第二个参数是用于逻辑处理的函数,可以是匿名的或是其他地方定义的函数名。不同的请求动词可以定义相同的路径,只需要切换动词就可以进入对应的处理逻辑。

curl -X PUT http://localhost:8080/article
curl -X POST http://localhost:8080/article
curl -X GET http://localhost:8080/article
curl -X DELETE http://localhost:8080/article

路由参数

GET请求有两种,一种是在URL后加上 ?name=pingye ,这种是有参数名的,另一种是在路径中直接加上参数值 /article/1 ,这种没有参数名,需要在代码中解析参数。

protocol://hostname:[port]/path/[query]#fragment

我们先来看路由携带参数值的玩法,这里有一道题,怎么利用Gin获取下面链接的参数值 1

Gin框架系列02:路由与参数

实现方式非常简单,只需要在路由中设置好占位符 :id ,冒号为占位符的标志,冒号后面的参数名可以自定义,Gin会将路由与请求地址进行匹配,若匹配成功会将 1 赋值为占位符 :id ,只需调用 c.Param 就可以获取 id 的值。

router.GET("/article/:id", func(c *gin.Context) {
  id := c.Param("id")
  c.String(200, id)
})

但是, :id 占位符会存在一个问题,如果 id 参数值传空就会有 404 的错误提示。

Gin框架系列02:路由与参数

于是Gin提供了另一种占位符 *id ,使用它就可以达到取空值的目的。

router.GET("/article/*id", func(c *gin.Context) {
  id := c.Param("id")
  c.String(200, id)
})

普通参数

除了路由携带参数值外,接下来看比较传统的 GET 传参方式。

http://localhost:8080/welcome?firstname=Jane&lastname=Doe

可以通过 c.Queryc.DefaultQuery 方法获取问号后的参数。

router.GET("/welcome", func(c *gin.Context) {
   firstname := c.DefaultQuery("firstname", "pingyeaa")
   lastname := c.Query("lastname")
   c.String(200, firstname+" "+lastname)
})

这两者最终都调用了 GetQuery 方法,唯一的区别是 DefaultQuery 做了默认值处理。

func (c *Context) DefaultQuery(key, defaultValue string) string {
    if value, ok := c.GetQuery(key); ok {
        return value
    }
    return defaultValue
}

func (c *Context) Query(key string) string {
    value, _ := c.GetQuery(key)
    return value
}

表单参数

从HTML提交过来的表单 form 内容同样也可以轻松获取。

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,
  })
})
curl -d "message=pingye" http://localhost:8080/form_post
{"message":"pingye","nick":"anonymous","status":"posted"}

数组类型参数

有时候(例如复选框)前端页面会传来数组类型的值,这种类型 name 相同,但存储的内容不同。

POST /post?ids[a]=1234&ids[b]=hello HTTP/1.1
Content-Type: application/x-www-form-urlencoded

依然是一个 QueryMap 方法就搞定,该方法默认返回 map 类型。

router.GET("/post", func(c *gin.Context) {
  ids := c.QueryMap("ids")
  c.String(200, ids["a"]+" "+ids["b"])
})
curl http://localhost:8080/post?ids[a]=pingye&ids[b]=hehe
pingye hehe

文件上传

一般情况下,文件上传会由前端直接传给云存储服务商,比如阿里云、七牛云等,比较少的场景会传给自己的服务器。为了避免 书到用时方恨少 的情况发生,我们来了解一下。

Gin提供了 FormFile 方法获取文件流,这个方法返回了一个 FileHeader 类型的变量,可以调用 Filename 属性来查看文件名。

type FileHeader struct {
   Filename string
   Header   textproto.MIMEHeader
   Size     int64

   content []byte
   tmpfile string
}
router.POST("/upload", func(c *gin.Context) {
  file, _ := c.FormFile("file")
  c.String(200, file.Filename)
})

通过 curl 请求接口,可以看到轻松获取文件名称。

curl -X POST http://localhost:8080/upload \
  -F "file=@/Users/enoch/Downloads/IMG_9216.JPG" \
  -H "Content-Type: multipart/form-data"
IMG_9216.JPG

当然不止可以拿到文件名,我们还可以使用 SaveUploadedFile 方法将文件保存到某个地方,文件保存时要确保有目标目录的操作权限。

router.POST("/upload", func(c *gin.Context) {
        file, _ := c.FormFile("file")
        c.String(200, file.Filename)
        err := c.SaveUploadedFile(file, "/Users/enoch/Desktop/ab.png")
        if err != nil {
            c.String(500, err.Error())
        }
})

路由分组

当接口发生重大变更(比如入参出参)时,考虑到向下兼容,一般会新增一个接口,但是又希望新接口的名称显而易见地看出是老接口的升级版,那么就可以在接口名前加上版本号 v1/article 这种形式。

v1 := r.Group("v1")
{
  v1.POST("/login", func(c *gin.Context) {
    c.String(200, "v1/login")
  })
  v1.POST("/submit", func(c *gin.Context) {
    c.String(200, "v1/submit")
  })
}

v2 := r.Group("v2")
{
  v2.POST("/login", func(c *gin.Context) {
    c.String(200, "v2/login")
  })
  v2.POST("/submit", func(c *gin.Context) {
    c.String(200, "v2/submit")
  })
}
curl -X POST http://localhost:8080/v1/login
curl -X POST http://localhost:8080/v2/login

Go语言库代码示例,欢迎star

https://github.com/pingyeaa/g...

感谢大家的观看,如果觉得文章对你有所帮助,欢迎关注公众号「平也」,聚焦 Go 语言与技术原理。

Gin框架系列02:路由与参数


以上所述就是小编给大家介绍的《Gin框架系列02:路由与参数》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

反应式设计模式

反应式设计模式

Roland Kuhn、Brian Hanafee、Jamie Allen / 何品、邱嘉和、王石冲、林炜翔审校 / 清华大学出版社 / 2019-1-1 / 98.00 元

《反应式设计模式》介绍反应式应用程序设计的原则、模式和经典实践,讲述如何用断路器模式将运行缓慢的组件与其他组件隔开、如何用事务序列(Saga)模式实现多阶段事务以及如何通过分片模式来划分数据集,分析如何保持源代码的可读性以及系统的可测试性(即使在存在许多潜在交互和失败点的情况下)。 主要内容 ? “反应式宣言”指南 ? 流量控制、有界一致性、容错等模式 ? 得之不易的关于“什么行不通”的经验 ? ......一起来看看 《反应式设计模式》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具