Gin基本使用

Gin框架使用
*基于httprouter开发的web框架
*提供Martini风格的API,但比Martini要快40倍
*非常轻量级,使用起来非常简洁
Gin框架安装与使用
*安装:go get -u github.com/gin-gonic/gin
*import"github.com/gin-gonic/gin"
第一个Gin程序

package main

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

func main(){
r := gin.Default()//创建一个默认的路由引擎
r.GET("/ping",func(c *gin.Context){//创建测试的路由
//GET:请求方式    /ping:请求的路径
//当客户端以GET方法请求/ping路径时,会执行后面的匿名函数
//c.JSON:返回JSON格式的数据
    c.JSON(200,gin.H{
   "message":"pong",
})
   })
   //启动HTTP服务,默认在0.0.0.0:8200启动服务
   r.Run(":8200")
}

1.首先,我们使用了gin.Default()生成了一个实例,这个实例即WSGI应用程序(Web服务器网关接口)。
2.接下来,我们使用了r.GET("/",…)声明了一个路由,告诉Gin什么样的URL(在www上,每一信息资源都有统一的且在网上唯一的地址,该地址就叫URL)能触发传入的函数,这个函数返回我们想要显示在用户浏览器中的信息。
3.最后用r.Run()函数来让应用运行在本地服务器上,默认监听端口是8200,可以传入参数设置端口,例如r.Run(":9999")即运行在9999端口。
4.然后使用浏览器打开127.0.0.1:8200/ping就能看到一串JSON字符串
请求路由-多种请求

package main

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

func main(){
	r := gin.Default()
	r.GET("/get",func(c *gin.Context){
		c.String(200,"get")
	})
	r.POST("/post",func(c *gin.Context){
		c.String(200,"post")
	})
	r.Handle("DELETE","/delete",
		func(c *gin.Context){
			c.String(200,"delete")
		})
	r.Any("/any",func(c *gin.Context){
		c.String(200,"any")
	})
	r.Run()
}

请求路由-静态文件夹

package main

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

func main(){
	r := gin.Default()
    r.Static("/assets","./assets")
	//先设置路由,再设置相对文件夹
	//另外一种写法
    r.StaticFS("/static",http.Dir("static"))
	//先设置路由,再设置资源
	//设置单个静态文件
	r.StaticFile("/favicon.ico",
		"./favicon.ico")
	//设置路由,设置资源
	r.Run()//启动服务器
}

请求路由-参数作为url

package main

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

func main(){
	r := gin.Default()
	r.GET("/:name/:id",func(c *gin.Context){
		c.JSON(200,gin.H{
			"name":c.Param("name"),
			"id":c.Param("id"),
		})
	})
	r.Run()
}

请求路由-泛绑定

package main

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

func main(){
	r := gin.Default()
	r.GET("/user/*action",
		func(c *gin.Context){
			c.String(200,"hello world")
		})
	r.Run()
}

获取请求参数-获取GET参数

package main

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

func main(){
	r := gin.Default()
	r.GET("/test",func(c *gin.Context){
		firstName := c.Query("first_name")
		lastName := c.DefaultQuery("last_name",
		"last_default_name")
		c.String(http.StatusOK,"%s,%s",
			firstName,lastName)
	})
	r.Run(":8080")
}

获取请求参数-获取body内容

package main

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

func main(){
	r := gin.Default()
	r.POST("/test",func(c *gin.Context){
		bodyByts,err := ioutil.ReadAll(c.Request.Body)
		if err != nil{
			c.String(http.StatusBadRequest,err.Error())
			c.Abort()
		}
		c.String(http.StatusOK,string(bodyByts))
	})
	r.Run()
}

获取请求参数-获取bind参数

package main

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

type Person struct{
	Name string   `form:"name"`
	Address string    `form:"address"`
	Birthday time.Time   `form:"birthday"`
}
func main(){
	r := gin.Default()
    r.GET("/testing",testing)
	r.POST("/testing",testing)
	r.Run()
}

func testing(c *gin.Context){
    var person Person
    if err := c.ShouldBind(&person);err==nil{
    	c.String(200,"%v",person)
	}else{
		c.String(200,"person bind error:%v",err)
	}
}

验证请求参数-结构体验证

package main

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

type Person struct{
	Age int    `form:"age" binding:"required,gt=10"`
	Name string    `form:"name" binding:"required"`
	Address string  `form:"address" binding:"required"`
}
func main(){
     r := gin.Default()
     r.GET("/testing",func(c *gin.Context){
         var person Person
         if err := c.ShouldBind(&person);err != nil{
         	c.String(500,"%v",err)
		 }
		 c.String(200,"%v",person)
	 })
     r.Run()
}

验证请求参数-自定义验证规则

package main

import (
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"net/http"
	"time"
)

type Booking struct{
	CheckIn time.Time `form:"check_in" validate:"required,bookableDate" time_format:"2006-01-02"`
	CheckOut time.Time `form:"check_out" validate:"required,gtfield=CheckIn" time_format:"2006-01-02`
}
func main(){
	r := gin.Default()
	validate := validator.New()
	validate.RegisterValidation("bookableDate",bookableDate)
	r.GET("/bookable",func(c *gin.Context){
		var book Booking
		if err := c.ShouldBind(&book);err != nil{
			c.JSON(http.StatusInterServerError,gin.H{
				"error":err.Error(),
			})
			c.Abort()
			return
		}
		if err := validate.Struct(book);err != nil{
			c.JSON(http.StatusInternalServerError,gin.H{
				"error":err.Error(),
			})
			c.Abort()
			return
		}
		c.JSON(http.StatusOK,gin.H{
			"message":"OK",
			"booking":book,
		})
	})
	r.Run()
}

func bookableDate(fl validator.FieldLevel)bool{
	if date,ok := fl.Field().Interface().(time.Time);ok{
		today := time.Now()
		if date.Unix() > today.Unix(){
			return true
		}
	}
	return false
}

验证请求参数-多语言翻译验证

package main

import (
	"github.com/gin-gonic/gin"
	en2 "github.com/go-playground/locales/en"
	zh2 "github.com/go-playground/locales/zh"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
	en_translations "gopkg.in/go-playground/validator.v9/translations/en"
	zh_translations "gopkg.in/go-playground/validator.v9/translations/zh"
)

type people struct{
	Age int `form:"age" validate:"required,gt=10"`
	Name string `form:"name" validate:"required"`
	Address string `form:"address" validate:"required"`
}
var(
	Uni *ut.UniversalTranslator
	Validate *validator.Validate
)
//验证信息多语言化
func main(){
    Validate = validator.New()//创建一个验证器
    zh := zh2.New()
    en := en2.New()
    Uni = ut.New(zh,en)//创建翻译器,翻译器里有可支持的语言
    r := gin.Default()
    r.GET("/testing",func(c *gin.Context){
    	locale := c.DefaultQuery("locale",
    		"zh")
    	trans,_ := Uni.GetTranslator("locale")
    	switch locale{
		case "zh":
			zh_translations.RegisterDefaultTranslations(Validate,trans)
		case "en":
			en_translations.RegisterDefaultTranslations(Validate,trans)
		default:
			zh_translations.RegisterDefaultTranslations(Validate,trans)
		}
		var person people
    	if err := c.ShouldBind(&person);err != nil{//结构绑定
    		c.String(500,"%v",err)
    		c.Abort()
    		return
		}
		if err := Validate.Struct(person);err != nil{
			errs := err.(validator.ValidationErrors)
			sliceErrs := []string{}
			for _,e := range errs{
				sliceErrs=append(sliceErrs,e.Translate(trans))
			}
            c.String(500,"%v",sliceErrs)
			c.Abort()
			return
		}
		c.String(200,"%v",person)
	})
    r.Run()
}

Gin中间件
Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等
中间件-使用

package main

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

func main(){
	r := gin.New()//这次用new来实现
    r.Use(gin.Logger())//设置中间件
    r.GET("/test",func(c *gin.Context){
    	name := c.DefaultQuery("name","default_name")
    	c.String(200,"%s",name)
	})
	r.Run()
}

那么,想把错误打印到文件应该怎么办呢?、

package main

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

func main(){
	f,_ := os.Create("gin.log")
	gin.DefaultWriter = io.MultiWriter(f)
	gin.DefaultErrorWriter = io.MultiWriter(f)
	r := gin.New()//这次用new来实现
    r.Use(gin.Logger())//设置中间件
    r.GET("/test",func(c *gin.Context){
    	name := c.DefaultQuery("name","default_name")
    	c.String(200,"%s",name)
	})
	r.Run()
}

gin.Recovery的作用

package main

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

func main(){
	f,_ := os.Create("gin.log")
	gin.DefaultWriter = io.MultiWriter(f)
	gin.DefaultErrorWriter = io.MultiWriter(f)
	r := gin.New()//这次用new来实现
    r.Use(gin.Logger(),gin.Recovery())//设置中间件
    r.GET("/test",func(c *gin.Context){
    	name := c.DefaultQuery("name","default_name")
    	panic("test panic")//加上这个程序不至于报错
    	c.String(200,"%s",name)
	})
	r.Run()
}

中间件-自定义中间件

上一篇:gin使用中间件


下一篇:15 【GET请求】获取路由上的参数值