一:gin介绍
在gin框架中,Engine被定义成为一个结构体,Engine代表gin框架的一个结构体定义,其中包含了路由组、中间件、页面渲染接口、框架配置设置等相关内容。
默认的Engine可以通过gin.Default进行创建,或者使用gin.New()同样可以创建。
1.1 gin.Default()和gin.New()
engine1 = gin.Default()engine2 = gin.New()
区别:gin.Default()和gin.New()的区别在于gin.Default也使用gin.New()创建engine实例,但是会默认使用Logger和Recovery中间件。
其中:
Logger是负责进行打印并输出日志的中间件,方便开发者进行程序调试;
Recovery中间件的作用是如果程序执行过程中遇到panic中断了服务,则Recovery会恢复程序执行,并返回服务器500内部错误。
通常情况下,我们使用默认的gin.Default创建Engine实例。
二.路由
2.1 访问
Handle
r.Handle("GET", "/hello", func(c *gin.Context) { //获取请求接口 fmt.Println(c.FullPath()) //获取字符串参数 浏览器调用格式://http://127.0.0.1:8889/hello?name=tom name := c.DefaultQuery("name", "chengc9") //有name就是返回name,没有的话返回默认值“chengc9” fmt.Println(name) //输出到前端 c.Writer.Write([]byte("Hello ," + name)) })
封装分类
r.GET("/hello", func(c *gin.Context) { name := c.DefaultQuery("name", "chengc9") //DefaultQuery 2个参数 c.JSON(200, gin.H{ "message": name, }) })
原型
// GET 是 router.Handle("GET", path, handle) 的一种封装后的简写,源码: func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes { return group.handle(http.MethodGet, relativePath, handlers) } //其中的HandlerFunc 结构体 type HandlerFunc func(*Context) //gin.H原型,因为在gin太经常使用了,所以定义了H type H map[string]any type any = interface{}
2.2url
分组
func main() { r:= gin.Default() // group: v1 v1 := router.Group("/v1") { v1.POST("/test1", test1) v1.POST("/test2", test2) } // group: v2 v2 := router.Group("/v2") { v2.POST("/test1", test1) v2.POST("/test2", test2) } router.Run(":80") }
类型
#REST的含义就是客户端与Web服务器之间进行交互的时候,使用HTTP协议中的4个请求方法代表不同的动作:get,put,post,delete func main() { r := gin.Default() r.GET("/book", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "GET", }) }) r.POST("/book", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "POST", }) }) r.PUT("/book", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "PUT", }) }) r.DELETE("/book", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "DELETE", }) }) }
2.3路由解析顺序
https://www.liwenzhou.com/posts/Go/gin-sourcecode/
基数树(Radix Tree)又称为PAT位树(Patricia Trie or crit bit tree),是一种更节省空间的前缀树(Trie Tree)。对于基数树的每个节点,如果该节点是唯一的子树的话,就和父节点合并。
为了获得更好的可伸缩性,每个树级别上的子节点都按Priority(优先级)
排序,其中优先级(最左列)就是在子节点(子节点、子子节点等等)中注册的句柄的数量。这样做有两个好处:
-
首先优先匹配被大多数路由路径包含的节点。这样可以让尽可能多的路由快速被定位。
-
类似于成本补偿。最长的路径可以被优先匹配,补偿体现在最长的路径需要花费更长的时间来定位,如果最长路径的节点能被优先匹配(即每次拿子节点都命中),那么路由匹配所花的时间不一定比短路径的路由长。下面展示了节点(每个
-
可以看做一个节点)匹配的路径:从左到右,从上到下。
Radix Tree
可以被认为是一棵简洁版的前缀树。我们注册路由的过程就是构造前缀树的过程,具有公共前缀的节点也共享一个公共父节点。假设我们现在注册有以下路由信息:
r := gin.Default() r.GET("/", func1) r.GET("/search/", func2) r.GET("/support/", func3) r.GET("/blog/", func4) r.GET("/blog/:post/", func5) r.GET("/about-us/", func6) r.GET("/about-us/team/", func7) r.GET("/contact/", func8) 那么我们会得到一个GET方法对应的路由树,具体结构如下: Priority Path Handle 9 \ *<1> 3 ├s nil 2 |├earch\ *<2> 1 |└upport\ *<3> 2 ├blog\ *<4> 1 | └:post nil 1 | └\ *<5> 2 ├about-us\ *<6> 1 | └team\ *<7> 1 └contact\ *<8> 上面最右边那一列每个*<数字>表示Handle处理函数的内存地址(一个指针)。从根节点遍历到叶子节点我们就能得到完整的路由表。
三.参数
3.1提取变量
path参数在url中以冒号开头的方式,如/:id/
、/:id/:action
querystring
指的是URL中?
后面携带的参数,querystring
参数在url中以DefaultQuery(),
Query()获取
//http://127.0.0.1:8080/book/2?name=chenc9&age=20 r.GET("/book/:id", func(c *gin.Context) { id:= c.Param("id") name := c.Query("name")
age := c.DefaultQuery("age",18) //输出json结果给调用方 c.JSON(http.StatusOK, gin.H{ "message": "ok", "name": name, "id": id,
"age": age, }) })
表单参数在url中以PostForm
(),DefaultPostForm
()获取
r.POST("/post", getPost)
func getPost(c *gin.Context) { id := c.Query("id") page := c.DefaultQuery("page", "0") name := c.PostForm("name") message := c.DefaultPostForm("message", "信息") c.JSON(http.StatusOK, gin.H{ "id": id, "page": page, "name": name, "message": message, }) }
作者:陈耿聪 —— 夕狱
出处:https://www.cnblogs.com/CGCong/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。