本文介绍了如何使用Gin框架处理接收到的GET、POST请求,并返回string、json、xml、html等格式。
Gin返回特定格式数据
首先来看接收到GET、POST请求时,如何返回对方想要的数据。GIN常见支持的返回格式有string、json、xml、html,下面将分别展示。
string、json、xml
package main
import (
"github.com/gin-gonic/gin"
"log"
"net/http"
)
func getString(c *gin.Context) {
// http.StatusOk 代表200状态码
c.String(http.StatusOK, "this is a string")
}
func getJson(c *gin.Context) {
// http.StatusOk 代表200状态码
// 第二个参数可以是任意类型的数据
c.JSON(http.StatusOK, map[string]any{
"message": "this is json value",
})
}
func getXml(c *gin.Context) {
// gin.H 就是map[string]any的缩写
c.XML(http.StatusOK, gin.H{
"success": true,
"msg": "this is xml value",
})
}
func main() {
// 创建默认路由引擎
r := gin.Default()
r.GET("/string", getString)
r.GET("/json", getJson)
r.GET("/xml", getXml)
// 指定运行的端口
err := r.Run(":8080")
// 处理错误
if err != nil {
log.Fatal(err)
return
}
}
string
json
xml
html
如要返回html页面,需要另外进行一些简单的配置。
首先我们在当前目录新建一个views文件夹,用于存放要显示的html文件,这边借用一下百度的首页,将下面的文件填入views文件夹下的baidu.html中。
<!DOCTYPE html>
<!--STATUS OK-->
<html lang="zh/cn">
<head>
<meta http-equiv=content-type content=text/html charset=utf-8>
<meta content=always name=referrer>
<link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css>
<title>{{.title}}</title>
</head> <body link=#0000cc>
<div id=wrapper>
<div id=head>
<div class=head_wrapper>
<div class=s_form>
<div class=s_form_wrapper>
<div id=lg>
<img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129>
</div>
<form id=form name=f action="/post/baidu" class=fm method="post">
<input type=hidden name=bdorz_come value=1>
<input type=hidden name=ie value=utf-8>
<input type=hidden name=f value=8>
<input type=hidden name=rsv_bp value=1>
<input type=hidden name=rsv_idx value=1>
<input type=hidden name=tn value=baidu>
<span class="bg s_ipt_wr">
<input id=kw name="content" class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr">
<input type=submit id=su value=百度一下 class="bg s_btn">
</span>
</form>
</div>
</div>
<div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> 登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div>
<div id=ftCon>
<div id=ftConw>
<p id=lh>
<a href=http://home.baidu.com>关于百度</a>
<a href=http://ir.baidu.com>About Baidu</a>
</p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a>
<a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>
京ICP证030173号
<img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
好了,现在项目的结构是这样的。
然后,编辑main.go,添加加载html文件的代码,以及处理对应请求的代码。
package main
import (
"github.com/gin-gonic/gin"
"log"
"net/http"
)
func getHtml(c *gin.Context) {
// http.StatusOk 代表200状态码
c.HTML(http.StatusOK, "baidu.html", gin.H{
// 这边的数据可以被html接收到
"title": "this is html",
})
}
func main() {
// 创建默认路由引擎
r := gin.Default()
// 加载模版文件
r.LoadHTMLGlob("views/*")
r.GET("/html", getHtml)
// 指定运行的端口
err := r.Run(":8080")
// 处理错误
if err != nil {
log.Fatal(err)
return
}
}
然后访问http://localhost:8080/html,显示如下页面,小功告成。
可以发现,这边网站的标签页名称变成了“this is html”,这是因为在html中,使用了
GET、POST请求数据解析方式
这部分介绍了如何从接收到的GET、POST请求中,获取其携带的参数,并将其绑定到GO代码自己定义的结构体中。
GET
解析参数
接受GET请求,并解析其携带的参数
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
type LoginData struct {
User string `form:"user" binding:"required"`
Password string `form:"password" binding:"required"`
}
func main() {
router := gin.Default()
router.GET("/get/json", func(c *gin.Context) {
username := c.DefaultQuery("username", "root")
password := c.DefaultQuery("password", "123456")
page := c.DefaultQuery("page", "1")
c.JSON(200, gin.H{
"login": LoginData{
User: username,
Password: password,
},
"page": page,
})
})
err := router.Run(":8080")
if err != nil {
return
}
}
绑定到结构体
接受GET请求,并将其携带的参数解析到结构体。
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type LoginData struct {
User string `form:"user" binding:"required"`
Password string `form:"password" binding:"required"`
}
func main() {
router := gin.Default()
router.LoadHTMLGlob("views/*")
router.GET("/get/login", func(c *gin.Context) {
data := LoginData{}
if c.ShouldBind(&data) == nil {
if data.User == "root" && data.Password == "123456" {
c.JSON(200, gin.H{"status": "you are logged in"})
} else {
c.JSON(401, gin.H{"status": "unauthorized"})
}
}
})
err := router.Run(":8080")
if err != nil {
return
}
}
POST
POST处理FORM表单
获取post请求,FORM表单中携带的数据,这边借用了上面修改过的百度那个界面。
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type LoginData struct {
User string `form:"user" binding:"required"`
Password string `form:"password" binding:"required"`
}
func main() {
router := gin.Default()
router.POST("/post/baidu", func(c *gin.Context) {
searchContent := c.PostForm("content")
c.JSON(http.StatusOK, gin.H{
"content": searchContent,
})
})
err := router.Run(":8080")
if err != nil {
return
}
}
绑定到结构体
接受POST请求,并将传过来的数据解析到结构体,支持多种类型的数据解析,如JSON、XML、FORM表单。
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
type LoginData struct {
User string `form:"user" binding:"required"`
Password string `form:"password" binding:"required"`
}
func main() {
router := gin.Default()
router.POST("/login", func(c *gin.Context) {
// 使用 ShouldBind 方法自动绑定:
var data LoginData
// 在这种情况下,将自动选择合适的绑定
if c.ShouldBind(&data) == nil {
fmt.Println(data.User, data.Password)
if data.User == "root" && data.Password == "123456" {
c.JSON(200, gin.H{"status": "you are logged in"})
} else {
c.JSON(401, gin.H{"status": "unauthorized"})
}
}
})
err := router.Run(":8080")
if err != nil {
return
}
}
接受POST请求,获取携带的XML数据,在处理微信和支付宝接口时,我们常接收到xml格式的返回值数据。
package main
import (
"encoding/xml"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
type LoginData struct {
User string `form:"user" xml:"user" binding:"required"`
Password string `form:"password" xml:"password" binding:"required"`
}
func main() {
router := gin.Default()
router.POST("/post/xml", func(c *gin.Context) {
xmlSliceData, err := c.GetRawData()
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": err.Error(),
})
}
data := LoginData{}
if err := xml.Unmarshal(xmlSliceData, &data); err == nil {
fmt.Printf("%#v\n", data)
if data.User == "root" && data.Password == "123456" {
c.JSON(200, gin.H{"status": "you are logged in"})
} else {
c.JSON(401, gin.H{"status": "unauthorized"})
}
} else {
c.JSON(http.StatusBadRequest, gin.H{
"code": http.StatusBadRequest,
"msg": err.Error(),
})
}
})
err := router.Run(":8080")
if err != nil {
return
}
}