• 【Golang】Gin处理GET、POST请求


    本文介绍了如何使用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>
    
    <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>hao123a> <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('+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录');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 Baidua>
                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中,使用了{​{.title}},修改title为传入的变量,使用双花括号加一个点获取。

    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
    	}
    }
    
  • 相关阅读:
    [JavaWeb]——JWT令牌技术,如何从获取JWT令牌
    【LeetCode】No.108. Convert Sorted Array to Binary Search Tree -- Java Version
    Polygon zkEVM——Hermez 2.0简介
    cocos2d-x Android原生平台与Lua交互
    JVM:常用的四种垃圾回收机制
    第七章,相似矩阵及其应用,5-正定二次型
    【Vue插件】一款很好用的vue日历插件——vue-sweet-calendar
    博客项目(前后端分离)(servlet实战演练)
    nginx负载均衡配置无效解决记录
    【Android】Loader及LoaderManager的使用和源码分析
  • 原文地址:https://blog.csdn.net/Valour616/article/details/139804504