使用 Web 框架,可以在开发项目时更高效。Web 框架一般会支持基础功能,比如路由、处理请求参数、渲染返回结果、中间件等。
本文我们介绍一款轻量级 Web 框架 Gin 框架。
示例代码:
package mainimport"github.com/gin-gonic/gin"func main(){ r :=gin.Default()r.GET("/ping",func(c*gin.Context){ c.JSON(200,gin.H{"message":"pong",})})r.Run()}
输出结果:
curl-s http://127.0.0.1:8080/ping | jq{"message":"pong"}
阅读上面这段代码,我们导入三方库 github.com/gin-gonic/gin,使用 gin.Default() 函数创建一个使用 Logger 和 Recovery 中间件的 Engine 实例(框架实例)。
然后使用 r.GET() 方法创建一个处理器,实际上 r.GET() 是 r.Handle() 的快捷方式。
最后,使用 r.Run() 方法(默认监听地址 0.0.0.0:8080)绑定处理器到 http.Server,并开始监听和处理 http 请求,实际上 r.Run() 方法是 http.ListenAndServe() 函数的快捷方式。
使用 Gin 框架注册路由,调用框架实例的方法即可,Gin 框架提供 Handle() 方法,可以方便我们注册任意 HTTP 方法的路由,示例代码:
package main import "github.com/gin-gonic/gin" func main() { r := gin.Default() r.Handle("GET", "/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) r.Run() }
阅读上面这段代码,我们可以发现 r.Handle() 方法接收 3 个参数,第一个是 HTTP方法,第二个是路径,第三个是处理器函数。
Gin 框架还提供了一些 HTTP 方法的快捷方式,例如:r.GET()、 r.POST()、r.DELETE()、r.PATCH()、r.PUT()、r.OPTIONS()、r.HEAD()。
此外,Gin 框架还提供了一个可以匹配所有 HTTP 方法的快捷方式,r.Any(),和一个可以匹配指定 HTTP 方法的快捷方式,r.Match()。
接下来,我们介绍 Gin 框架怎么接收请求参数。我们按照请求参数的格式,分别介绍各种格式的请求参数的接收方式。
请求字符串(queryString)是请求地址中英文问号 ? 后面的参数,例如:
http://127.0.0.1:8080/user_info?username=frank
示例代码:
package mainimport"github.com/gin-gonic/gin"func main(){ r :=gin.Default()r.GET("/user_info",GetUserInfo)r.Run()} func GetUserInfo(c*gin.Context){ userName :=c.Query("username")c.JSON(200,gin.H{"username": userName,})}
输出结果:
curl-s http://127.0.0.1:8080/user_info\?username\=frank | jq{"username":"frank"}
package mainimport"github.com/gin-gonic/gin"func main(){ r :=gin.Default()r.POST("/user_info",PostUserInfo)r.Run()} func PostUserInfo(c*gin.Context){ userName :=c.PostForm("username")c.JSON(200,gin.H{"username": userName,})}
输出结果:
curl-s-X POST-d"username=frank"http://127.0.0.1:8080/user_info\?username\=frank | jq{"username":"frank"}
以上示例代码,都是使用默认 Content-Type Content-Type:application/x-www-form-urlencoded,当 Content-Type:application/json 时,我们需要使用 c.GetRawData() 方法接收请求参数,示例代码:
package mainimport("encoding/json""github.com/gin-gonic/gin")func main(){ r :=gin.Default()r.POST("/user_info",JsonUserInfo)r.Run()} func JsonUserInfo(c*gin.Context){// 定义 struct 或 mapvar m map[string]interface{} b,_ :=c.GetRawData()_=json.Unmarshal(b,&m)c.JSON(200,gin.H{"username": m["username"],})}
输出结果:
curl-s-H"Content-Type: application/json"-X POST-d'{"username":"frank"}'http://127.0.0.1:8080/user_info\?username\=frank | jq{"username":"frank"}
以上几种方式,是我们开发项目时比较常用的方式,但是,我们在使用以上几种方式时,需要事先约定 Content-Type。
所以 Gin 框架还有另外一种接收请求参数的方式,也就是使用 c.ShouldBind() 方法。
它可以通过检查 HTTP Method 和 Content-Type 的值,自动将 quertString、form 表单、json 和 xml 的值解析到 struct。
示例代码:
package mainimport("encoding/json""github.com/gin-gonic/gin")func main(){ r :=gin.Default()r.POST("/user_info",ShouldBindUserInfo)r.Run()}typeUserInfo struct { Username string`form:"username" json:"username" xml:"username"`} func ShouldBindUserInfo(c*gin.Context){ var userInfo UserInfo _=c.ShouldBind(&userInfo)c.JSON(200,gin.H{"username": userInfo.Username,})}
输出结果:
// application/jsoncurl-s-H"Content-Type: application/json"-X POST-d'{"username":"frank"}'http://127.0.0.1:8080/user_info\?username\=frank | jq{"username":"frank"}// application/xmlcurl-s-H"Content-Type: application/xml"-X POST-d"<user_info><username>frank</username></user_info>"http://127.0.0.1:8080/user_info\?username\=frank | jq{"username":"frank"}// application/x-www-form-urlencodedcurl-s-X POST-d"username=frank"http://127.0.0.1:8080/user_info\?username\=frank | jq{"username":"frank"}// HTTP Method GETcurl-s http://127.0.0.1:8080/user_info\?username\=frank | jq{"username":"frank"}
需要注意的是,自定义结构体的标签,不要漏掉。否则,将无法将请求参数的值解析到结构体中。
本文我们介绍 Go 语言高性能 Web 框架 Gin 框架的路由和请求参数的一般使用方式,建议读者朋友们动手运行文章中的示例代码。
[1] Gin 文档: https://gin-gonic.com/zh-cn/docs/
[2] Gin 源码: https://github.com/gin-gonic/gin/blob/master/context.go