gin入门使用

使用 go mod 下载依赖

首先咱们使用 go moudle来管理依赖, go版本要求在 1.11.1 及以上git

export GO111MODULE=on

export GOPROXY=https://mirrors.aliyun.com/goproxy/
复制代码

初始化 mod 配置github

go mod init

>在当前目录下会生成 go.mod 文件, 做为依赖配置.
复制代码

build项目后会自动下载依赖json

其中在实际项目中发现 goland 没法识别项目代码, 须要 在 goland 的 setting 里设置启用 Go Modulesapi

goland Preference -> Go -> Go Modules(vgo)
-> Enable Go Modules(vgo)intergration
复制代码

开始以第一个项目

package main

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

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

	// get 方式请求
	r.GET("/get", func(c *gin.Context) {
		c.JSON(200, "get")
	})

	// post 方式请求
	r.POST("/post", func(c *gin.Context) {
		c.JSON(200, "post")
	})

	// 任意类型请求
	r.Any("any", func(c *gin.Context) {
		c.JSON(200, "any")
	})

	// handle 指定方式请求
	r.Handle("POST", "/handle_post", func(c *gin.Context) {
		c.JSON(200, "handle post")
	})
   
        //r.Run(":8888") 监听 8888 端口
        r.Run()
}
复制代码

这里咱们定义了经常使用的 get post方法, 经过 debug 能够看到 any 方式为咱们建立了全部的能够实用的请求的方式, 最后使用了 handle 方式指定方法参数. gin.Default 配置默认的参数, Run 启动 http 服务, 默认监听 8080 端口bash

curl -XPOST http://127.0.0.1:8080/post
output:
    "post"

curl -XPOST http://127.0.0.1:8080/handle_post
output:
   "handle post"
复制代码

gin 的路由同请求方式下不能重复定义, 不然启动将会异常退出markdown

获取请求参数

package main

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

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

	// get 方式请求
	r.GET("/getUser/:uid", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"uid": c.Param("uid"),
		})
	})

	r.Run()
}
复制代码

output:app

curl http://127.0.0.1:8080/getUser/1451
output:
   {"uid":"1451"}
复制代码

http.StatusOK 引用的 net/http 包中的状态码定义, c.Param() 获取 uid 的值curl

前缀匹配

在工做中咱们但愿路由匹配到某个前缀oop

r.GET("/user/*a", func(c *gin.Context) {
	c.String(http.StatusOK, "hello user")
})
复制代码

这样只要请求到 user 就能够拦截到了, 注意在 gin 里是不容许再设置相似 /user/admin 这样的路由了. 这里是没有路由优先级的.post

请求参数默认值

r.GET("/user", func(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
    	"name": c.Query("name"),
    	"sex":  c.DefaultQuery("sex", "女"),
    })
})
复制代码

请求示例

curl http://127.0.0.1:8080/user?name=1
output:
    {"name":"1","sex":"女"}
复制代码

获取post方式请求的参数

c.String(http.StatusOK, c.PostForm("name"))
//获取name值, 默认值为小明
c.String(http.StatusOK, c.DefaultPostForm("name", "小明")
复制代码

请求的json获取

r.POST("/user", func(c *gin.Context) {
	bodyBytes, error := ioutil.ReadAll(c.Request.Body)
	if error != nil {
		c.String(http.StatusOK, error.Error())
		c.Abort()
	}

	c.String(http.StatusOK, string(bodyBytes))
})
复制代码
curl -XPOST http://127.0.0.1:8080/user?name=1 -d {"name":1}
output:
  {name:1}
复制代码

可是经过 readAll 读取后再获取值是获取不到的. 解决方案就是再将值写回去.

如何将获取到的json绑定到结构体上

package main

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

type requestUser struct {
	Name string `form:"name"`
	Uid  int    `form:"uid"`
	Age  int    `form:"age"`
	Date time.Time `form:"date"`
}

func main() {
	r := gin.Default()
	r.POST("/user", userAction)
	r.Run()
}

func userAction(c *gin.Context) {
	var requestUser requestUser
    
        //这里是根据请求的content-type进行解析(能够解析json)
	if err := c.ShouldBind(&requestUser); err != nil {
		c.String(http.StatusOK, err.Error())
		c.Abort()
	}

	c.String(http.StatusOK, "%v", requestUser)
}

复制代码
curl -XPOST http://127.0.0.1:8080/user -d 'name=xiaoming&age=23'
output:
    {xiaoming 0 23}

curl -XPOST http://127.0.0.1:8080/user -d 'name=xiaoming&date=2019-01-01'
output:
    parsing time "2019-01-01" as "2006-01-02T15:04:05Z07:00": cannot parse "" as "T"{xiaoming 0 0 0001-01-01 00:00:00 +0000 UTC}
复制代码

注意咱们在传递时间格式的时候解析发生错误.

这里咱们须要定义时间格式结构体解决

type requestUser struct {
	Name string `form:"name"`
	Uid  int    `form:"uid"`
	Age  int    `form:"age"`
	Date time.Time `form:"date" time_format:"2006-01-02"`
}
复制代码

验证

type requestUser struct {
	Name string `form:"name" binding:"required,len=10"`
	Uid  int    `form:"uid"`
	Age  int    `form:"age" binding:"required,gt=10"`
}
复制代码
curl -H "Content-Type:application/json" -XPOST http://127.0.0.1:8080/user -d '{"name":"xiaoming234342342342342","age":11}'
output:
    Key: 'requestUser.Name' Error:Field validation for 'Name' failed on the 'len' tag{xiaoming234342342342342 0 11}
复制代码

更多验证规则: godoc.org/gopkg.in/go…

###自定义 validator

type requestUser struct {
	Name string `form:"name" binding:"required,len=10"`
	Uid  int    `form:"uid" binding:"checkUidAvailable"`
	Age  int    `form:"age" binding:"required,gt=10"`
}
复制代码

编写 checkUidAvailable

// Structure
func checkUidAvailable(field validator.FieldLevel) bool {
	if fieldValue, ok := field.Field().Interface().(int); ok {
		//随机几率
		if rand.Intn(2) == fieldValue {
			return true
		}
	}

	return false
}
复制代码

在 main方法中绑定

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

	r.POST("/user", userAction)

        //绑定
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		v.RegisterValidation("checkUidAvailable", checkUidAvailable)
	}

	r.Run()
}
复制代码

方法执行, ShouldBind 自动验证

func userAction(c *gin.Context) {
	var requestUser requestUser

	if err := c.ShouldBind(&requestUser); err != nil {
		c.String(http.StatusInternalServerError, err.Error())
		c.Abort()
		return
	}
	
	c.String(http.StatusOK, "%v", requestUser)
}
复制代码

中间件

f, _ := os.Create("gin.log")
gin.DefaultWriter = io.MultiWriter(f)
gin.DefaultErrorWriter = io.MultiWriter(f)

r := gin.New()
r.Use(gin.Logger(), gin.Recovery())
复制代码

上面咱们使用了 gin.New 实例的方式声明, r.Use使用了两个中间件, 一个为日志, 另外一个为碰见 panic 抛出异常最上层, 让程序正常运行.

f, _ := os.Create("gin.log")
gin.DefaultWriter = io.MultiWriter(f)
gin.DefaultErrorWriter = io.MultiWriter(f)

r := gin.Default()
复制代码

默认日志是输出到控制台, 将日志和错误日志所有输出到 gin.log

自定义中间件

func ipAuthMiddleWare() gin.HandlerFunc {
    return func(c *gin.Context) {
    	ipList := []string{
    		"127.0.0.1",
    	}
    
    	flag := false
    	clientIp := c.ClientIP()
    	for _, host := range ipList {
    		if clientIp != host {
    			flag = true
    			break
    		}
    	}
    
    	if !flag {
    		c.String(http.StatusOK, "error")
    		c.Abort()
    	}
    }
}

---

r.Use(gin.Logger(), gin.Recovery(), ipAuthMiddleWare())
复制代码

路由组

api := r.Group("/api")
{
	api.GET("user", userAction)
}
复制代码

访问 127.0.0.1:8080/api/user 路由组中引入中间件

api := r.Group("/api").Use(ipAuthMiddleWare())
{
	api.GET("user", userAction)
}
复制代码

一样使用 use 便可

附录

json处理: colobu.com/2017/06/21/…

相关文章
相关标签/搜索