Gin框架

Gin框架

数据绑定

简单来说,,就是根据Body数据类型,将数据赋值到指定的结构体变量中 (类似于序列化和反序列化) 。

Must bind

  • ⽅法:Bind , BindJSON , BindXML , BindQuery , BindYAML
  • 如果存在绑定错误,则⽤c终⽌请求,使⽤ c.AbortWithError (400) .SetType (ErrorTypeBind) 即可。如果想更好地控制⾏为,可以考虑使⽤ShouldBind等效⽅法.

Should bind

  • 方法:ShouldBind , ShouldBindJSON , ShouldBindXML , ShouldBindQuery , ShouldBindYAXML
  • ⾏为:这些⽅法使⽤ShouldBindWith。如果存在绑定错误,则返回错误.

例子:

package main

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

type Login struct {
	User     string `form:"username" json:"user" uri:"user" xml:"user"  binding:"required"`
	Password string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}

func main() {
	router := gin.Default()
	// binding JSON
	// Example for binding JSON ({"user": "ls", "password": "123456"})
	router.POST("/loginJSON", func(c *gin.Context) {
		var data Login
		// 其实就是将request中ContentType 类型去动态解析
		// 如果是mustBind,类型必须一样
		if err := c.ShouldBind(&data); err != nil {
			//c.String(http.StatusOK, "error")
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
		if data.User != "ls" || data.Password != "123456" {
			c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
			return
		}
		c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
	})

	router.Run(":8080")
}

模板

package main

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

func main() {
	router := gin.Default()
	// 加载文件夹下全部的模板
	router.LoadHTMLGlob("templates/**/*")
	// 加载个别模板
	// router.LoadHTMLFiles("templates/template1.html", "templates/template2.html")

	// 定义路由
	router.GET("/index", func(c *gin.Context) {
		//根据完整⽂件名渲染模板,并传递参数
		c.HTML(http.StatusOK, "index.tmpl", gin.H{
			"title": "Main website",
		})
	})

	// 定义路由
	router.GET("/shop/index", func(c *gin.Context) {
		//根据完整⽂件名渲染模板,并传递参数
		c.HTML(http.StatusOK, "/shop/index.tmpl", gin.H{
			"title": "shop website",
		})
	})

	router.Run(":8080")
}

模板继承

  • 模板继承
  • ⽂件响应
  • 重定向(http重定向)
package main

import (
	"github.com/gin-contrib/multitemplate"
	"github.com/gin-gonic/gin"
	"net/http"
	"path/filepath"
)

// 装载模板
func loadTemplates(templatesDir string) multitemplate.Renderer {
	r := multitemplate.NewRenderer()

	// 加载布局,用于被继承
	layouts, err := filepath.Glob(templatesDir + "/layouts/*.html")
	if err != nil {
		panic(err.Error())
	}

	// 加载模板,继承layouts
	includes, err := filepath.Glob(templatesDir + "/includes/*.html")
	if err != nil {
		panic(err.Error())
	}

	// 为layouts/和includes/⽬录⽣成 templates map
	for _, include := range includes {
		layoutCopy := make([]string, len(layouts))
		copy(layoutCopy, layouts)
		files := append(layoutCopy, include)
		r.AddFromFiles(filepath.Base(include), files...)
	}

	return r
}

// 模板继承练习
func main() {
	r := gin.Default()
	r.HTMLRender = loadTemplates("./templates")

	// 路径映射,之后,模板文件中,可以使用/xx/zjl.jpg来访问
	//r.Static("xx", "./images")

	// http服务器,把文件暴露出来,点击即可下载
	r.StaticFS("/showDir", http.Dir("."))

	r.GET("/base/index", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.html", gin.H{
			"content": "/base/index",
		})
	})

	r.GET("/base/home", func(c *gin.Context) {
		c.HTML(http.StatusOK, "home.html", gin.H{
			"content": "/base.home",
		})
	})

	// 重定向,get请求后,转到别的网站
	r.GET("/redirect", func(c *gin.Context) {
		// ⽀持内部和外部的重定向
		c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com/")
		//c.Redirect(http.StatusMovedPermanently, "/base/home")
	})

	r.Run(":8080")
}

同步异步

goroutine 机制可以⽅便地实现异步处理。当在中间件或处理程序中启动新的Goroutines时,你不应该在原始上下⽂使⽤它,你必须使⽤只读的副本。

package main

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

func main() {
	r := gin.Default()

	// 1. 异步
	r.GET("/long_async", func(c *gin.Context) {
		// goroutine 中只能使⽤只读的上下⽂ c.Copy()
		cCp := c.Copy()
		go func() {
			time.Sleep(5 * time.Second)
			// 注意使⽤只读上下⽂
			log.Println("Done! in path " + cCp.Request.URL.Path)
		}()
	})

	// 2. 同步
	r.GET("/long_sync", func(c *gin.Context) {
		time.Sleep(5 * time.Second)
		// 注意可以使⽤原始上下⽂
		log.Println("Done! in path " + c.Request.URL.Path)
	})
	
	r.Run(":8080")
}

你可能感兴趣的:(Go)