一起来玩玩gin - Go语言中文社区

一起来玩玩gin


     人生如梦  一樽还酹江月

gin定位:一款高性能的go web框架

代码已push,地址:https://gitlab.com/wanglan/gin-coms.git

目录

项目结构

main.go(多组路由)

以order.go测试GET各请求

以customer.go测试POST/PUT请求

调用目标API前先校验(多处理器)

多路由API执行前校验


项目结构

main.go(多组路由)

分两组路由,验证路由分组功能

package main

import (
	"gin-coms/config"
	"gin-coms/routers"
	"github.com/gin-gonic/gin"
)

func main() {
	router := gin.Default()
	// 第一组路由:以/api开头
	apiGroup := router.Group("/api")
	{
		routers.CusRoute(apiGroup)
		routers.OrderRoute(apiGroup)
	}

	// 第二组路由:以/other开头
	otherGroup := router.Group("/other")
	{
		routers.OtherRoute(otherGroup)
	}

	//config.InitMysql()
	router.Run(config.ComsAddress + ":" + config.ComsPort)
}

以order.go测试GET各请求

package routers

import (
	"fmt"
	"gin-coms/model"
	"github.com/gin-gonic/gin"
	"net/http"
)

func OrderRoute(group *gin.RouterGroup) {
	group.GET("/order", OrderList)
	group.GET("/order/:ID", OrderDetail)
    // URL的问号会带参数name
    // http://localhost:8000/api/orderByName?name=无名
	group.GET("/orderByName", OrderByName) 
}

func OrderByName(c *gin.Context) {
	name := c.Query("name") //获取URL路径参数
	fmt.Println("您要查询的订单名称是:", name)
	c.JSON(http.StatusOK, "hello 这里是/api/orderByName路由,您要查询的订单名称是:"+name)
	//c.String(http.StatusOK, "hello 这里是/api/order路由")
}

func OrderDetail(c *gin.Context) {
	id := c.Param("ID") //获取URL路径参数
	fmt.Println("您要查询的是", id, "号订单。")
	c.JSON(http.StatusOK, "hello 这里是/api/order/:ID路由,您要查询的是"+id+"号订单。")
	//c.String(http.StatusOK, "hello 这里是/api/order路由")
}

func OrderList(c *gin.Context) {
	var orderList []model.Order
	order1 := model.Order{Name: "订单1", OrderPrice: 88}
	order2 := model.Order{Name: "订单2", OrderPrice: 99}
	orderList = append(orderList, order1, order2)
	c.String(http.StatusOK, "hello 这里是/api/order路由,此处返回订单列表:", orderList)

	// 如果要返回自定义结构体类型ReturnStruct,需要改源码,在type HandlerFunc func(*Context)后加返回值ReturnStruct即可。
	//return model.ReturnStruct{Code:http.StatusOK,Message:"hello 这里是/api/order路由,此处返回订单列表!",Data:orderList}
}

URL1:http://localhost:8000/api/orderByName?name=无名

URL2:http://localhost:8000/api/order/9

order列表:

控制台日志如下:

以customer.go测试POST/PUT请求

分别以两种方式获取请求体参数

package routers

import (
	"fmt"
	"gin-coms/model"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
)

func CusRoute(group *gin.RouterGroup) {
	group.POST("/cus", CreateCustomer)
	group.PUT("/cus", UpdateCustomer)
}

func CreateCustomer(c *gin.Context) {
	var cus model.Customer
	err := c.BindJSON(&cus) // 获取请求体参数,请求头为application/json
	if err != nil {
		log.Println(err.Error())
	}
	fmt.Println("用户", cus, "已创建。")
	c.JSON(http.StatusOK, "用户已创建。")
}

func UpdateCustomer(c *gin.Context) {
	name := c.PostForm("name")	// 获取请求体参数,请求头为application/x-www-form-urlencoded
	gender := c.PostForm("gender")
	fmt.Println("用户", name,"  ",gender, "已修改。")
	c.JSON(http.StatusOK, "用户已修改。")
}

测试POST

测试PUT

控制台打印:

调用目标API前先校验(多处理器)

我想在走进orderList接口之前先执行下CheckOrder,CheckOrder里面是我自己的校验逻辑,,应该怎么做?

修改order.go中的orderlist路由,增加CheckOrder处理器:

group.GET("/order",CheckOrder, OrderList)    // 增加一个处理器

func CheckOrder(c *gin.Context){
	fmt.Println("---进入check函数---")
	if c.Request.Header.Get("token") == "enyduuamlm2cdcs=="{
		fmt.Println("验证通过!")
		return
	}
	c.Abort()    // 执行该行之后下一个处理器将不会执行
	c.JSON(http.StatusUnauthorized,"验证失败!")
}

以正确情况验证一下:

日志打印:

如果不按CheckOrder中的校验规则来,或者header中有token字段但内容错误:

即,错误情况下报401,请求终止。

上面这种方式对于单个需要校验的处理器而言还行,如果是大规模路由呢?

多路由API执行前校验

以第二组路由other模块试试。other模块有两个模块的路由:OneRoute和OtherRoute,目前简便起见各只有一个接口,我只想让OtherRoute下的所有路由走CheckByToken处理器,OneRoute不用验证就能访问,应该怎么做?

修改代码,变动如下:


func main() {
	router := gin.New()
	router.Use(gin.Logger())
	router.Use(gin.Recovery())
	// 第一组路由:以/api开头
	apiGroup := router.Group("/api")
	{
		routers.CusRoute(apiGroup)
		routers.OrderRoute(apiGroup)
	}

	// 第二组路由:以/other开头
	otherGroup := router.Group("/other")
	{       routers.OneRoute(otherGroup)
            // 可以放多个中间件,如otherGroup.Use(CheckByToken(),CheckBySession()),按顺序执行
            // CheckByToken()对otherGroup.Use(CheckByToken())之后的路由起作用
		otherGroup.Use(CheckByToken())	
		routers.OtherRoute(otherGroup)
	}

	//config.InitMysql()
	router.Run(config.ComsAddress + ":" + config.ComsPort)
}

func CheckByToken() gin.HandlerFunc{
	return func(c *gin.Context){
                fmt.Println("---进入CheckByToken函数---")
		if c.Request.Header.Get("token") == "token-abcde"{
			fmt.Println("验证token成功!")
			// 验证通过时继续往下走访问下一个中间件
			c.Next()
		} else {
			// 验证不通过时请求终止
			c.Abort()
			c.JSON(http.StatusUnauthorized,"验证失败!")
		}
	}
}

func CheckBySession() gin.HandlerFunc{
	return func(c *gin.Context){
		
	}
}

other路由模块:

func OtherRoute(group *gin.RouterGroup){
	group.GET("/test", OtherList)
}

func OneRoute(group *gin.RouterGroup){
	group.GET("/one", oneList)
}

func oneList(c *gin.Context){
	fmt.Println("成功进入oneList接口")
	c.String(http.StatusOK, "hello, 这里是/other/one路由")
}

func OtherList(c *gin.Context){
	fmt.Println("成功进入OtherList接口")
	c.String(http.StatusOK, "hello, 这里是/other/test路由")
}

访问/other/test并且带正确token验证一下:

访问/other/test并且带错误token验证一下:

上面两步控制台打印如下:

即用户访问/other/test时肯定会先执行CheckByToken处理器,接下来分别以正确和不正确的token来

验证下/other/one:

控制台日志:

即,根本不会进CheckByToken处理器,它对/other/one接口(OneRoute下的所有路由)是没有任何作用的,那么上面的做法就得到了验证,我们的目的也就达成了。

gin的多处理器逻辑这块和马卡龙(macaron)是非常类似的。

 

 

 

 

 

 

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/hyzx_9987/article/details/103976117
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-02-24 22:24:59
  • 阅读 ( 1186 )
  • 分类:Go Web框架

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢