gin框架入门实战教程10_12

**Gin **框架入门实战系列教程

主讲教师:(大地)
在线文档:https://www.itying.com/gin
我的专栏:https://www.itying.com/category-79-b0.html

十、**Gin **中自定义 Model

10.1 、关于 Model

:::tips
如果我们的应用非常简单的话,我们可以在 Controller 里面处理常见的业务逻辑。但是如果 我们有一个功能想在多个控制器、或者多个模板里面复用的话,那么我们就可以把公共的功 能单独抽取出来作为一个模块(Model)。 Model 是逐步抽象的过程,一般我们会在 Model 里面封装一些公共的方法让不同 Controller 使用,也可以在 Model 中实现和数据库打交道
:::

10.2 、Model 里面封装公共的方法

**1 **、新建 models/ tools.go

package  models

import  (
    "crypto/md5"
    "fmt"
    "time"

    "github.com/astaxie/beego"
)

//时间戳间戳转换成日期
func  UnixToDate(timestamp  int)  string  {

    t  :=  time.Unix(int64(timestamp),  0)

    return  t.Format("2006-01-02   15:04:05")
}

//日期转换成时间戳 2020-05-02  15:04:05
func  DateToUnix(str  string)   int64  {
    template  :=  "2006-01-02  15:04:05"
    t,  err   :=  time.ParseInLocation(template,  str,  time.Local)
    if  err   !=  nil  {
        return  0
    }
    return  t.Unix()
}

func  GetUnix()  int64  {
    return  time.Now().Unix()
}
func  GetDate()  string  {
    template  :=  "2006-01-02  15:04:05"
    return  time.Now().Format(template)
}
func  GetDay()  string  {
    template  :=  "20060102"
    return  time.Now().Format(template)
}

func  Md5(str  string)  string  {
    data  :=  []byte(str)
    return  fmt.Sprintf("%x\n",  md5.Sum(data))
}

10.3 、控制器中调用 Model

package  controllers

import  (
    "gin_demo/models"
)

day  :=  models.GetDay()

10.4 、调用 Model 注册全局模板函数

models/tools.go
//时间戳间戳转换成日期

func  UnixToDate(timestamp  int64)  string  {

    t  :=  time.Unix(timestamp,  0)

    return  t.Format("2006-01-02   15:04:05")
}

main.go
//注册全局模板函数 注意顺序,注册模板函数需要在加载模板上面

r  :=  gin.Default()
r.SetFuncMap(template.FuncMap{
    "unixToDate" :  models.UnixToDate,
})

控制器

func  (c  UserController)  Add(ctx   *gin.Context)  {
    ctx.HTML(http.StatusOK,  "admin/user/add.html",  gin.H{
        "now" :  models.GetUnix(),
    })
}

模板

<h2>{{.now   |  unixToDate}}</h2>

10.5 、Golang Md5 加密

打开 golang 包对应的网站:https://pkg.go.dev/ ,搜索 md5
方法一:

| data := []byte(" 123456")
has := md5.Sum(data)
md5str := fmt.Sprintf(“%x”, has)

fmt.Println(md5str)

方法二:

| h := md5.New()
io.WriteString(h, " 123456")

fmt.Printf(“%x\n”, h.Sum(nil))

十一、**Gin **文件上传

注意:需要在上传文件的 form 表单上面需要加入 enctype=“multipart/form-data”

11.1 、单文件上传

https://gin-gonic.com/zh-cn/docs/examples/upload-file/single-file/

官方示例:

func  main()  {
    router  :=  gin.Default()
    //  为 multipart  forms   设置较低的内存限制 (默认是 32   MiB)
    router.MaxMultipartMemory  =  8  <<   20    //  8   MiB
    router.POST("/upload",  func(c   *gin.Context)  {
        //  单文件
        file,  _  :=  c.FormFile("file")
        log.Println(file.Filename)

        //  上传文件至指定目录
        c.SaveUploadedFile(file,  dst)

        c.String(http.StatusOK,  fmt.Sprintf("'%s'  uploaded!",  file.Filename)) })
    router.Run(" :8080")
}

项目中实现文件上传:
**1 **、定义模板 需要在上传文件的 form 表单上面需要加入 enctype=“multipart/form-data”

<!--  相当于给模板定义一个名字 define     end  成对出现-->
{{  define   "admin/user/add.html"  }}
<!DOCTYPE  html>
<html  lang="en">
<head>
<meta  charset="UTF-8">
<meta  http-equiv="X-UA-Compatible"  content="IE=edge">
<meta  name="viewport"  content="width=device-width,   initial-scale=1.0"> <title>Document</title>
</head>
<body>
<form  action="/admin/user/doAdd"   method=" post"  enctype="multipart/form-data">
用户名: <input  type="text"   name="username"   placeholder="用户名">  <br>  <br> 头  像:<input  type="file"   name="face"><br>  <br>
<input  type="submit"  value="提交">
</form>
</body>
</html>
{{  end  }}

**2 **、定义业务逻辑

func  (c  UserController)  DoAdd(ctx  *gin.Context)  {
    username  :=  ctx.PostForm("username")
    file,  err  :=  ctx.FormFile("face")

    if  err   !=  nil  {
        ctx.JSON(http.StatusInternalServerError,  gin.H{
            "message" :  err.Error(),
        })
        return
    }
    //  上传文件到指定的目录
    dst  :=  path.Join("./static/upload",  file.Filename)
    fmt.Println(dst)
    ctx.SaveUploadedFile(file,  dst)
    ctx.JSON(http.StatusOK,  gin.H{
        "message" :    fmt.Sprintf("'%s'   uploaded!",  file.Filename),
        "                   "
        username  :  username,
    })
}      

11.2 、多文件上传–不同名字的多个文件

1 、定义模板 需要在上传文件的 form 表单上面需要加入 enctype=“multipart/form-data”

<!--  相当于给模板定义一个名字 define     end  成对出现-->
{{  define   "admin/user/add.html"  }}
<!DOCTYPE  html>
  <html  lang="en">
  <head>
  <meta  charset="UTF-8">
  <meta  http-equiv="X-UA-Compatible"  content="IE=edge">
  <meta  name="viewport"  content="width=device-width,   initial-scale=1.0"> <title>Document</title>
  </head>
  <body>
  <form  action="/admin/user/doAdd"   method=" post"  enctype="multipart/form-data">
  用户名: <input  type="text"   name="username"   placeholder="用户名">  <br>  <br>
  头  像 1<input  type="file"   name="face1"><br>  <br>
  头  像 2<input  type="file"   name="face2"><br>  <br>
  <input  type="submit"  value="提交">
  </form>
  </body>
  </html>
{{  end  }}

**2 **、定义业务逻辑

func  (c  UserController)  DoAdd(ctx  *gin.Context)  {
  username  :=  ctx.PostForm("username")
  face1,  err1   :=  ctx.FormFile("face1")
  face2,  err2   :=  ctx.FormFile("face2")
  //  上传文件到指定的目录
  if  err1  ==  nil  {
    dst1  :=  path.Join("./static/upload",  face1.Filename)
    ctx.SaveUploadedFile(face1,  dst1)
  }
  if  err2  ==  nil  {
    dst2  :=  path.Join("./static/upload",  face2.Filename)
    ctx.SaveUploadedFile(face2,  dst2)
  }

  ctx.JSON(http.StatusOK,  gin.H{

    "message" :     "文件上传成功",
      "                   "
    username  :  username,
  })
  //  ctx.String(200,   username)
}

11.3 、多文件上传–相同名字的多个文件

参考:https://gin-gonic.com/zh-cn/docs/examples/upload-file/multiple-file/

**1 **、定义模板 需要在上传文件的 form 表单上面需要加入 enctype=“multipart/form-data”

<!--  相当于给模板定义一个名字 define     end  成对出现-->
{{  define   "admin/user/add.html"  }}
<!DOCTYPE  html>
  <html  lang="en">
  <head>
  <meta  charset="UTF-8">
  <meta  http-equiv="X-UA-Compatible"  content="IE=edge">
  <meta  name="viewport"  content="width=device-width,   initial-scale=1.0"> <title>Document</title>
  </head>
  <body>
  <form  action="/admin/user/doAdd"   method=" post"  enctype="multipart/form-data">
  用户名: <input  type="text"   name="username"   placeholder="用户名">  <br>  <br>
  头  像 1<input  type="file"   name="face[]"><br>  <br>
  头  像 2<input  type="file"   name="face[]"><br>  <br>
  <input  type="submit"  value="提交">
  </form>
  </body>
  </html>
{{  end  }}

**2 **、定义业务逻辑

func  (c  UserController)  DoAdd(ctx  *gin.Context)  {
    username  :=  ctx.PostForm("username")

    //  Multipart  form
    form,  _  :=  ctx.MultipartForm()
    files  :=  form.File["face[]"]

    //  var  dst;
    for  _,  file  :=  range  files  {
        //  上传文件至指定目录
        dst  :=  path.Join("./static/upload",  file.Filename)
        ctx.SaveUploadedFile(file,  dst)
    }

    ctx.JSON(http.StatusOK,  gin.H{
        "message" :     "文件上传成功",
        "                   "
        username  :  username,
    })
}

11.4 、文件上传 按照日期存储

**1 **、定义模板 需要在上传文件的 form 表单上面需要加入 enctype=“multipart/form-data”

<!--  相当于给模板定义一个名字 define     end  成对出现-->
{{  define   "admin/user/add.html"  }}
<!DOCTYPE  html>
  <html  lang="en">
  <head>
  <meta  charset="UTF-8">
  <meta  http-equiv="X-UA-Compatible"  content="IE=edge">
  <meta  name="viewport"  content="width=device-width,   initial-scale=1.0"> <title>Document</title>
  </head>
  <body>
  <form  action="/admin/user/doAdd"   method=" post"  enctype="multipart/form-data">
  用户名: <input  type="text"   name="username"   placeholder="用户名">  <br>  <br> 头  像: <input  type="file"   name="face"><br>  <br>

  <input  type="submit"  value="提交">
  </form>
  </body>
  </html>

{{  end  }}

**2 **、定义业务逻辑

func  (c  UserController)  DoAdd(ctx  *gin.Context)  {
    username  :=  ctx.PostForm("username")
    //1 、获取上传的文件
    file,  err1  :=  ctx.FormFile("face")

    if  err1  ==  nil  {

        //2 、获取后缀名 判断类型是否正确  .jpg   .png  .gif  .jpeg
        extName  :=  path.Ext(file.Filename)

        allowExtMap  :=  map[string]bool{
            ".jpg" :    true,
            ".png" :    true,
            ".gif" :    true,
            ".jpeg" :  true,
        }

        if  _,  ok  :=  allowExtMap[extName];   !ok  {
            ctx.String(200,  "文件类型不合法")
            return
        }
        //3 、创建图片保存目录  static/upload/20200623
        day  :=  models.GetDay()
        dir  :=  "./static/upload/"  +  day

        if  err   :=  os.MkdirAll(dir,  0666);  err   !=  nil  {
            log.Error(err)
        }
        //4 、生成文件名称   144325235235.png
        fileUnixName  :=  strconv.FormatInt(models.GetUnix(),   10)
        //static/upload/20200623/ 144325235235.png
        saveDir  :=  path.Join(dir,  fileUnixName+extName)
        ctx.SaveUploadedFile(file,  saveDir)
    }
    ctx.JSON(http.StatusOK,  gin.H{
        "message" :     "文件上传成功",
        "                   "
        username  :  username,
    })
    //  ctx.String(200,   username)
}

**3 **、models/tools.go

package  models

import  (
    "crypto/md5"
    "fmt"
    "time"
)

//时间戳间戳转换成日期
func  UnixToDate(timestamp  int)  string  {

    t  :=  time.Unix(int64(timestamp),  0)

    return  t.Format("2006-01-02   15:04:05")
}

//日期转换成时间戳 2020-05-02  15:04:05
func  DateToUnix(str  string)   int64  {
    template  :=  "2006-01-02  15:04:05"
    t,  err   :=  time.ParseInLocation(template,  str,  time.Local)
    if  err   !=  nil  {
        beego.Info(err)
        return  0
    }
    return  t.Unix()
}

func  GetUnix()  int64  {
    return  time.Now().Unix()
}
func  GetDate()  string  {
    template  :=  "2006-01-02  15:04:05"
    return  time.Now().Format(template)
}
func  GetDay()  string  {
    template  :=  "20060102"
    return  time.Now().Format(template)

}

func  Md5(str  string)  string  {
    data  :=  []byte(str)
    return  fmt.Sprintf("%x\n",  md5.Sum(data))
}

func  Hello(in  string)  (out  string)  {
    out  =  in  +  "world"
    return
}

十二、Gin 中的 Cookie

12.1 、Cookie 介绍

:::tips
● HTTP 是无状态协议。简单地说,当你浏览了一个页面,然后转到同一个网站的另一个页 面,服务器无法认识到这是同一个浏览器在访问同一个网站。每一次的访问,都是没有任何 关系的。如果我们要实现多个页面之间共享数据的话我们就可以使用 Cookie 或者 Session 实 现
● cookie 是存储于访问者计算机的浏览器中。可以让我们用同一个浏览器访问同一个域名 的时候共享数据。
:::

12.2 、Cookie 能实现的功能

:::tips
1 、保持用户登录状态
2 、保存用户浏览的历史记录
3 、猜你喜欢,智能推荐
4 、电商网站的加入购物车
:::

12.3 、设置和获取 Cookie

https://gin-gonic.com/zh-cn/docs/examples/cookie/

设置 Cookie

c.SetCookie(name,  value  string,   maxAge  int,  path,  domain  string,  secure,   httpOnly   bool)

第一个参数 第二个参数
第三个参
:::info
key
value
过期时间.如果只想设置 Cookie 的保存路径而不想设置存活时间,可以在第三个

参数中传递 nil
第四个参数 cookie 的路径
第五个参数 cookie 的路径 Domain作用域 本地调试配置成 localhost , 正式上线配置成域名
第六个参数是 secure ,当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中 才有效
第七个参数 httpOnly,是微软对 COOKIE 做的扩展。如果在 COOKIE 中设置了“ httpOnly”属性, 则通过程序(JS 脚本、applet 等)将无法读取到 COOKIE 信息,防止 XSS 攻击产生
获取 Cookie
:::

cookie,  err   :=  c.Cookie("name")

完整 **demo

**

package  main

import  (
    "gin_demo/models"
    "html/template"

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

func  main()  {
    r  :=  gin.Default()
    r.SetFuncMap(template.FuncMap{
        "unixToDate" :  models.UnixToDate,
    })

    r.GET("/",  func(c   *gin.Context)  {
        c.SetCookie("usrename",  "张三",  3600,   "/",  "localhost",  false,  true)
        c.String(200,  "首页")
    })

    r.GET("/user",  func(c   *gin.Context)  {
        username,  _  :=  c.Cookie("usrename")
        c.String(200,  "用户-"+username)
    })

    r.Run(" :8080")
}

12.4 、多个二级域名共享 cookie

:::info
1 、分别把 a.itying.com 和 b.itying.com 解析到我们的服务器
2 、我们想的是用户在 a.itying.com 中设置 Cookie 信息后在 b.itying.com 中获取刚才设置的 cookie ,也就是实现多个二级域名共享 cookie
这时候的话我们就可以这样设置 cookie
:::

c.SetCookie("usrename",  "张三",  3600,   "/",  ".itying.com",  false,  true)
  • 20
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值