go gin框架学习总结


简介

Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确,具有快速灵活,容错方便等特点

hello world

package main

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

func main() {
   // 1.创建路由
   r := gin.Default()
   // 2.绑定路由规则,执行的函数
   // gin.Context,封装了request和response
   r.GET("/hello", func(c *gin.Context) {
      c.String(http.StatusOK, "hello World!")
   })
   // 3.监听端口,默认在8080
   // Run("里面不指定端口号默认为8080")
   r.Run(":8000")
}

访问:http://localhost:8000/hello

结果:hello World!

路由

gin 框架中采用的路由库是基于httprouter做的https://github.com/julienschmidt/httprouter

restful 风格的api

gin支持Restful风格的API,即Representational State Transfer的缩写。直接翻译的意思是”表现层状态转化”,是一种互联网应用程序的API设计理念:URL定位资源,用HTTP描述操作

  • 获取文章: GET /blog/1
  • 添加文章: POST /blog/1
  • 修改文件: PUT /blog/1
  • 删除文章: DELETE /blog/1

url都是一样的,用于定位资源,HTTP方法描述操作

参数获取

api参数获取

可以通过Context的Param方法来获取API参数

url参数获取

URL参数可以通过DefaultQuery()或Query()方法获取

DefaultQuery()若参数不村则,返回默认值,Query()若不存在,返回空串

func main() {
   // 1.创建路由
   r := gin.Default()
   // 2.绑定路由规则,执行的函数
   // gin.Context,封装了request和response
   r.GET("/hello/:name/*action", func(c *gin.Context) {
      // 获取api中的参数
      name := c.Param("name")
      action := c.Param("action")
      // 获取url中的参数
      password := c.Query("password")
      c.String(http.StatusOK, "hello %s, your action is %s!, your password:%s", name, action, password)
   })

   // 3.监听端口,默认在8080
   // Run("里面不指定端口号默认为8080")
   r.Run(":8000")
}

访问http://localhost:8000/hello/张三/testaction?password=123

结果hello 张三, your action is /testaction!, your password:123

表单参数

  • 表单传输为post请求,http常见的传输格式为四种:

    • application/json
    • application/x-www-form-urlencoded
    • application/xml
    • multipart/form-data
  • 表单参数可以通过PostForm()方法获取,该方法默认解析的是x-www-form-urlencoded或from-data格式的参数

username := c.PostForm("username")
password := c.PostForm("userpassword")

获取单个文件

file, err := c.FormFile("file")

获取多个文件

form, err := c.MultipartForm()
files := form.File["files"]

routes group

  • routes group是为了管理一些相同的URL
  • httproter会将所有路由规则构造一颗前缀树
    func main() {
       // 1.创建路由
       // 默认使用了2个中间件Logger(), Recovery()
       r := gin.Default()
       // 路由组1 ,处理GET请求
       v1 := r.Group("/v1")
       // {} 是书写规范
       {
          v1.GET("/login", login)
          v1.GET("submit", submit)
       }
       v2 := r.Group("/v2")
       {
          v2.POST("/login", login)
          v2.POST("/submit", submit)
       }
       r.Run(":8000")
    }
    
    func login(c *gin.Context) {
       name := c.DefaultQuery("name", "jack")
       c.String(200, fmt.Sprintf("hello %s\n", name))
    }
    
    func submit(c *gin.Context) {
       name := c.DefaultQuery("name", "lily")
       c.String(200, fmt.Sprintf("hello %s\n", name))
    }

数据解析与绑定

json解析与绑定

// 将request的body中的数据,自动按照json格式解析到结构体
err := c.ShouldBindJSON(&json)

表单解析与绑定

// Bind()默认解析并绑定form格式
// 根据请求头中content-type自动推断
err := c.Bind(&form);

url解析与绑定

// Bind()默认解析并绑定form格式
// 根据请求头中content-type自动推断
err := c.ShouldBindUri(&login)

gin渲染

各种数据格式的响应

  • json
    c.JSON(http.StatusOK, gin.H{"msg": fmt.Sprintf("恭喜你登录成功,欢迎:%s", user.Name)})
  • struct
    c.JSON(http.StatusOK, user)  // 跟json一样,调用c.JSON方法
  • xml
    c.XML(http.StatusOK, gin.H{"msg": fmt.Sprintf("恭喜你登录成功,欢迎:%s", user.Name)})
    结果
    <map>
    	<msg>恭喜你登录成功,欢迎:zhangsan</msg>
    </map>
  • yaml
    c.YAML(http.StatusOK, gin.H{"msg": fmt.Sprintf("恭喜你登录成功,欢迎:%s", user.Name)})
    结果
    msg: 恭喜你登录成功,欢迎:zhangsan
  • protobuf

protobuf格式,谷歌开发的高效存储读取的工具

reps := []int64{int64(1), int64(2)}
// 定义数据
label := "label"
// 传protobuf格式数据
data := &protoexample.Test{
   Label: &label,
   Reps:  reps,
}
c.ProtoBuf(200, data)

结果

HTML模板响应

  • gin支持加载HTML模板, 然后根据模板参数进行配置并返回相应的数据,本质上就是字符串替换
// 加载模板文件
r.LoadHTMLGlob("html/*")
// 引入静态文件
r.Static("/assets", "./assets")
r.GET("/index", func(c *gin.Context) {
   c.HTML(http.StatusOK, "html/index.html", gin.H{"title": "我是标题", "address": "https://baidu.com"})
})

html/index.html

{{ define "html/index.html" }}
{{template "html/header" .}}
百度{{.address}}
{{template "html/footer" .}}
<img src="assets/1.jpg"/>
{{ end }}

html/header.html

{{define "html/header"}}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>{{.title}}</title>
</head>
<body>

{{end}}

html/footer.html

{{define "html/footer"}}
</body>
</html>
{{ end }}

重定向

// 重定向
r.GET("/bd", func(c *gin.Context) {
   c.Redirect(http.StatusMovedPermanently, "https://www.baidu.com")
})

中间件

// 定义中间
func TimeCost() gin.HandlerFunc {
   return func(c *gin.Context) {
      t := time.Now()
      fmt.Println("中间件开始执行了")
      // 设置变量到Context的key中,可以通过Get()取
      c.Set("request", "中间件")
      time.Sleep(time.Second * 3)
      status := c.Writer.Status()
      fmt.Println("中间件执行完毕", status)
      t2 := time.Since(t)
      fmt.Println("time:", t2)
      c.Set("time_cost", t2)
   }
}
r.Use(middleware.TimeCost())
// 测试中间件
r.GET("/test_middleware", func(c *gin.Context) {
   // 取值
   req, _ := c.Get("request")
   timeCost, _ := c.Get("time_cost")
   fmt.Println("request:", req)
   // 页面接收
   c.JSON(200, gin.H{"request": req, "time_cost": timeCost})
})

系统日志

中间件开始执行了
中间件执行完毕 200
time: 3.000636802s
request: 中间件

返回结果

{
	"request": "中间件",
	"time_cost": 3000636802
}

会话控制

  • HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出
  • Cookie就是解决HTTP协议无状态的方案之一,中文是小甜饼的意思
  • Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求
  • Cookie由服务器创建,并发送给浏览器,最终由浏览器保存
// 给客户端设置cookie
 //  maxAge int, 单位为秒
 // path,cookie所在目录
 // domain string,域名
 //   secure 是否智能通过https访问
 // httpOnly bool  是否允许别人通过js获取自己的cookie
 c.SetCookie("key_cookie", "value_cookie", 60, "/",
    "localhost", false, true)
  • 缺点

    • 不安全,明文
    • 增加带宽消耗
    • 可以被禁用
    • cookie有上限

Session

其实就是一个local store

日志


// Logging to a file.
f, _ := os.Create("gin.log")
gin.DefaultWriter = io.MultiWriter(f)

// 如果需要同时将日志写入文件和控制台,请使用以下代码。
// gin.DefaultWriter = io.MultiWriter(f, os.Stdout)
r := gin.Default()

参考

[1]gin框架

[2]https://github.com/julienschmidt/httprouter


文章作者: Alex
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Alex !
  目录