Gin框架: 路由解析与分组详解

参数获取与表单处理


1 )参数获取, 处理 Query 和 Params 请求

package main

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

var statusOK = http.StatusOK

func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()

	// 首页
	r.GET("/", func(c *gin.Context) {
		c.String(statusOK, "Welcome to %v", "Home Page")
	})

	// 用户页面
	r.GET("/user", func(c *gin.Context) {
		uid := c.Query("uid")
		page := c.DefaultQuery("page", "0") // 不传这个值,把0当做其默认值
		c.String(statusOK, "uid=%v page=%v", uid, page)
	})

	// 新闻页面
	r.GET("/news/:nid", func(c *gin.Context) {
		nid := c.Param("nid")
		c.String(statusOK, "newsID=%s", nid)
	})

	r.Run()
}
  • 访问: /user, 页面渲染出来的是: uid= page=0
  • 访问: /user?uid=1&page=1, 页面渲染出来的是: uid=1 page=1
  • 访问: /news/1, 页面渲染出来的是: newsID=1

2 )表单处理

  • 首先看下设定的结构

    yourGinProject/ ·······························  根目录
      ├── go.mod ··································  go mod 文件
      ├── go.sum ··································  go sum 文件
      ├── main.go ·································  main 文件
      └── tpls ····································· html模板目录
    	    └── web
    	          ├── profile.html
    	          └── user.html
    
  • 再设计下路由访问

    • GET /profile 获取 profile 页面
    • POST /doAddProfile 提交 profile 页面表单处理
    • GET /user 获取 user 页面
    • POST /doAddUser 提交 user 页面表单处理
    • GET /getUser?username=zhangsan&password=1111 查询某条user数据
    • POST /xml 提交xml数据处理
  • 主程序

    package main
    
    import (
    	"encoding/xml"
    	"net/http"
    	"github.com/gin-gonic/gin"
    )
    
    var statusOK = http.StatusOK
    var statusBadRequest = http.StatusBadRequest
    
    type UserInfo struct {
    	Username string `json:"username" form:"username"`
    	Password string `json:"password" form:"password"`
    }
    
    type Article struct {
    	Title   string `json:"title" xml:"title"`
    	Content string `json:"content" xml:"content"`
    }
    
    func main() {
    	// 创建一个默认的路由引擎
    	r := gin.Default()
    	// 加载模板 放在配置路由前面
    	r.LoadHTMLGlob("tpls/**/*")
    
      // 首页
    	r.GET("/", func(c *gin.Context) {
    		c.String(statusOK, "Welcome to %v", "Home Page")
    	})
    
    	// ---------------- profile 页面处理 --------------------
    	// 配置可访问的profile页面可以进行post演示
    	r.GET("/profile", func(c *gin.Context) {
    		c.HTML(statusOK, "web/profile.html", gin.H{})
    	})
    
    	// 获取表单post过来的数据
    	r.POST("/doAddProfile", func(c *gin.Context) {
    		// 参数处理
    		username := c.PostForm("username")
    		password := c.PostForm("password")
    		age := c.DefaultPostForm("age", "20") // 这里有一个默认的参数
    
    		// 响应出去
    		c.JSON(statusOK, gin.H{
    			"username": username,
    			"password": password,
    			"age":      age,
    		})
    	})
    
    	// ---------------- user 页面处理 --------------------
    	// 配置可访问的user页面可以进行post演示
    	r.GET("/user", func(c *gin.Context) {
    		c.HTML(statusOK, "web/user.html", gin.H{})
    	})
    
    	// 处理user页面提交出来的数据
    	r.POST("/doAddUser", func(c *gin.Context) {
    		// user结构体会作为接收参数的结构
    		user := &UserInfo{}
    		// 正常情况,使用 ShouldBind 来处理
    		// .ShouldBind()强大的功能,它能够基于请求自动
    		// 提取 JSON、form 表单和 QueryString 类型的数据
    		// 并把值绑定到指定的结构体对象
    		if err := c.ShouldBind(&user); err == nil {
    			// c.JSON(statusOK, &user)
    			c.JSON(statusOK, user) // 上下两者均可
    		} else {
    			// 错误处理
    			c.JSON(statusBadRequest, gin.H{
    				"err": err.Error(),
    			})
    		}
    	})
    
    	// ---------------- 模拟查询user接口 --------------------
    	// 访问参考: /getUser?username=zhangsan&password=1111
    	r.GET("/getUser", func(c *gin.Context) {
    		// 设定user结构体
    		user := &UserInfo{}
    		// 处理参数
    		if err := c.ShouldBind(&user); err == nil {
    			c.JSON(http.StatusOK, user)
    		} else {
    			c.JSON(http.StatusOK, gin.H{
    				"err": err.Error(),
    			})
    		}
    	})
    
    	// ---------------- 这里使用 postman 来提交xml --------------------
    	// 获取 Post Xml 数据
    	r.POST("/xml", func(c *gin.Context) {
    		// 准备结构体
    		article := &Article{}
    		// 获取原生xml数据
    		xmlSliceData, _ := c.GetRawData() //获取 c.Request.Body 读取请求数据
    
    		if err := xml.Unmarshal(xmlSliceData, &article); err == nil {
    			c.JSON(statusOK, article)
    		} else {
    			c.JSON(statusBadRequest, gin.H{
    				"err": err.Error(),
    			})
    		}
    	})
    
    	r.Run()
    }
    
  • html 页面

    • web/profile.html
      {{ define "web/profile.html" }}
      
        <form action="/doAddProfile" method="post">
            
            用户名:<input type="text" name="username" /> <br><br>
            密码:<input type="password" name="password" /> <br><br>      
      
            <input type="submit" value="提交">
        form>
      
      {{end}}
      
    • web/user.html
      {{ define "web/user.html" }}
      
        <form action="/doAddUser" method="post">
            
            用户名:<input type="text" name="username" /> <br><br>
            密码:<input type="password" name="password" /> <br><br>      
      
            <input type="submit" value="提交">
        form>
      
      {{end}}
      
  • 特别地,提交xml时的设置与响应

Gin框架: 路由解析与分组详解_第1张图片

路由分组处理

1 )简单分组

主程序

package main

import (
	"github.com/gin-gonic/gin"
)

func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()
	
	// 默认分组
	defaultRouters := r.Group("/")
	{
		defaultRouters.GET("/", func(c *gin.Context) {
			c.String(200, "首页")
		})
		defaultRouters.GET("/news", func(c *gin.Context) {
			c.String(200, "新闻")
		})
	}
	
	// api分组
	apiRouters := r.Group("/api")
	{
		apiRouters.GET("/", func(c *gin.Context) {
			c.String(200, "我是一个api接口")
		})
		apiRouters.GET("/userlist", func(c *gin.Context) {
			c.String(200, "我是一个api接口-userlist")
		})
		apiRouters.GET("/plist", func(c *gin.Context) {
			c.String(200, "我是一个api接口-plist")
		})
	}
	
	// admin分组
	adminRouters := r.Group("/admin")
	{
		adminRouters.GET("/", func(c *gin.Context) {
			c.String(200, "后台首页")
		})
		adminRouters.GET("/user", func(c *gin.Context) {
			c.String(200, "用户列表")
		})
		adminRouters.GET("/article", func(c *gin.Context) {
			c.String(200, "新闻列表")
		})
	}

	r.Run()
}

2 )按文件分组

  • 首先看下设定的结构
    yourGinProject/ ·······························  根目录
      ├── go.mod ··································  go mod 文件
      ├── go.sum ··································  go sum 文件
      ├── main.go ·································  main 文件
      └── tpls ····································· html模板目录
      |	    └── web
      |	          └── index.html
      └── routers ·································· 路由配置目录
    		├── webRouters.go
    		├── apiRouters.go
    		└── adminRouters.go
    

2.1 主程序

package main

import (
	"gin-demo/routers" // 注意,这里gin-demo是项目名称,需要一开始 go mod init gin-demo
	"github.com/gin-gonic/gin"
)

func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()

	// 配置默认路由
	routers.WebRoutersInit(r)
	
	// 配置api
	routers.ApiRoutersInit(r)

	// 配置admin
	routers.AdminRoutersInit(r)

	r.Run()
}

2.2 routers 包

2.1 webRouters.go

package routers

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

var statusOK = http.StatusOK

func WebRoutersInit(r *gin.Engine) {
	r.LoadHTMLGlob("tpls/**/*") // 配置模板路径,如果是通用的,这个配置应放在 main.go 中
	webRouters := r.Group("/")
	{
		webRouters.GET("/", func(c *gin.Context) {
			c.HTML(statusOK, "web/index.html", gin.H{
				"msg": "我是一个msg",
			})
		})
		webRouters.GET("/news", func(c *gin.Context) {
			c.String(statusOK, "新闻")
		})
	}
}

2.2 apiRouters.go

package routers

import "github.com/gin-gonic/gin"

func ApiRoutersInit(r *gin.Engine) {
	apiRouters := r.Group("/api")
	{
		apiRouters.GET("/", func(c *gin.Context) {
			c.String(200, "我是一个api接口")
		})
		apiRouters.GET("/userlist", func(c *gin.Context) {
			c.String(200, "我是一个api接口-userlist")
		})
	}
}

2.3 adminRouters.go

package routers

import "github.com/gin-gonic/gin"

func AdminRoutersInit(r *gin.Engine) {
	adminRouters := r.Group("/admin")
	{
		adminRouters.GET("/", func(c *gin.Context) {
			c.String(200, "后台首页")
		})
		adminRouters.GET("/user", func(c *gin.Context) {
			c.String(200, "用户列表")
		})
	}
}

你可能感兴趣的:(Golang,gin,golang)