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

回顾

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

请求动词

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

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

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实例化对象,接下来全部的路由操做都经过该对象使用便可。golang

file

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()
}复制代码

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

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服务器

file

实现方式很是简单,只须要在路由中设置好占位符: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的错误提示。app

file

因而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 github.com/pingyeaa/go…


感谢你们的观看,若是以为文章对你有所帮助,欢迎关注公众号「平也」,聚焦Go语言与技术原理。 关注我

相关文章
相关标签/搜索