Golang学习 Day_17 Gin框架02

本文详细介绍了Gin框架中如何进行路由分组、自定义中间件、控制器设计以及文件上传功能的实现,包括单个文件和多个同名文件的上传。同时,文章还涵盖了Cookie和Session的管理,展示了如何设置、读取和删除Cookie,以及如何使用cookie和redis存储Session。
摘要由CSDN通过智能技术生成

路由分组与抽离

package main


import (
    "fmt"
    "gin_05/routers"
    "text/template"
    "time"


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


func UnixToTime(timestamp int) string {
    fmt.Println(timestamp)
    t := time.Unix(int64(timestamp), 0)
    return t.Format("2006-01-02 15:04:05")
}


func main() {
    // 初始化路由
    r := gin.Default()


    //自定义模板函数
    r.SetFuncMap(template.FuncMap{
        "UnixToTime": UnixToTime,
    })


    // 配置模板文件
    // r.LoadHTMLGlob("templates/**/*")


    // 配置静态web目录 第一个参数表示路由,第二个参数表示映射目录
    r.Static("/static", "./static")


    routers.DefaultRoutersInit(r)


    routers.ApiRoutersInit(r)


    routers.AdminRoutersInit(r)


    r.Run()
}
package routers


import (
    "net/http"


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


func AdminRoutersInit(r *gin.Engine) {
    adminRouters := r.Group("/admin")
    {
        adminRouters.GET("/", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "后台首页")
        })


        adminRouters.GET("/user", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "用户列表")
        })
        adminRouters.GET("/article", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "新闻列表")
        })
        adminRouters.GET("/add", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "增加用户")
        })
        adminRouters.GET("/edit", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "修改用户")
        })


    }
}
package routers


import (
    "net/http"


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


func ApiRoutersInit(r *gin.Engine) {
    apiRouters := r.Group("/api")
    {
        apiRouters.GET("/", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "这是一个api接口")
        })


        apiRouters.GET("/userlist", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "这是一个api接口-userlist")
        })


        apiRouters.GET("/plist", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "这是一个api接口-plist")
        })


        apiRouters.GET("/cart", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "这是一个api接口-cart")
        })
    }
}
package routers


import (
    "net/http"


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


func ApiRoutersInit(r *gin.Engine) {
    apiRouters := r.Group("/api")
    {
        apiRouters.GET("/", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "这是一个api接口")
        })


        apiRouters.GET("/userlist", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "这是一个api接口-userlist")
        })


        apiRouters.GET("/plist", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "这是一个api接口-plist")
        })


        apiRouters.GET("/cart", func(ctx *gin.Context) {
            ctx.String(http.StatusOK, "这是一个api接口-cart")
        })
    }
}

Gin中自定义控制器

adminRouters.GET("/user", admin.UserController{}.Index)
adminRouters.GET("/user/add", admin.UserController{}.Add)
adminRouters.GET("/user/edit", admin.UserController{}.Edit)
package admin


import (
    "net/http"


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


type UserController struct {
}


func (con UserController) Index(ctx *gin.Context) {
    ctx.String(http.StatusOK, "用户列表")
}
func (con UserController) Add(ctx *gin.Context) {
    ctx.String(http.StatusOK, "增加用户")
}
func (con UserController) Edit(ctx *gin.Context) {
    ctx.String(http.StatusOK, "修改用户")
}
package admin


import (
    "net/http"


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


type ArticleController struct {
    BaseController
}


func (con ArticleController) Index(ctx *gin.Context) {
    // ctx.String(http.StatusOK, "文章列表")
    con.error(ctx)
}
func (con ArticleController) Add(ctx *gin.Context) {
    ctx.String(http.StatusOK, "增减文章")
}
func (con ArticleController) Edit(ctx *gin.Context) {
    ctx.String(http.StatusOK, "修改文章")
}
package admin


import (
    "net/http"

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


type ArticleController struct {
    BaseController
}


func (con ArticleController) Index(ctx *gin.Context) {
    // ctx.String(http.StatusOK, "文章列表")
    con.error(ctx)
}
func (con ArticleController) Add(ctx *gin.Context) {
    ctx.String(http.StatusOK, "增减文章")
}
func (con ArticleController) Edit(ctx *gin.Context) {
    ctx.String(http.StatusOK, "修改文章")
}
package routers


import (
    "gin_05/controllers/admin"


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


func AdminRoutersInit(r *gin.Engine) {
    adminRouters := r.Group("/admin")
    {
        adminRouters.GET("/", admin.IndexController{}.Index)
        adminRouters.GET("/user", admin.UserController{}.Index)
        adminRouters.GET("/user/add", admin.UserController{}.Add)
        adminRouters.GET("/user/edit", admin.UserController{}.Edit)
        adminRouters.GET("/article", admin.ArticleController{}.Index)
        adminRouters.GET("/article/add", admin.ArticleController{}.Add)
        adminRouters.GET("/article/edit", admin.ArticleController{}.Edit)


    }
}

Gin中间件

func initMiddleware(ctx *gin.Context) {
    fmt.Println("aaa")
}
r.GET("/", initMiddleware, func(ctx *gin.Context) {
    ctx.String(200, "gin首页")
})
r.GET("/news", initMiddleware, func(ctx *gin.Context) {
    ctx.String(200, "新闻页面")
})
r.GET("/login", initMiddleware, func(ctx *gin.Context) {
    ctx.String(200, "login")
})

ctx.Next()调用该请求的剩余处理程序

func initMiddleware(ctx *gin.Context) {
    start := time.Now().UnixNano()
    fmt.Println("1-这是一个中间件")
    ctx.Next()
    fmt.Println("2-这是一个中间件")
    end := time.Now().UnixNano()
    fmt.Println(end - start)
}

ctx.Abort()终止调用请求的剩余处理程序

func initMiddleware(ctx *gin.Context) {
    start := time.Now().UnixNano()
    fmt.Println("1-这是一个中间件")
    ctx.Abort()
    fmt.Println("2-这是一个中间件")
    end := time.Now().UnixNano()
    fmt.Println(end - start)
}

多个中间件

package main


import (
    "fmt"
    "text/template"
    "time"


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


type Article struct {
    Title   string
    Content string
}


type UserInfo struct {
    Username string `json:"username" form:"username"`
    Password string `json:"password" form:"password"`
}


func UnixToTime(timestamp int) string {
    fmt.Println(timestamp)
    t := time.Unix(int64(timestamp), 0)
    return t.Format("2006-01-02 15:04:05")
}


func initMiddleware1(ctx *gin.Context) {
    start := time.Now().UnixNano()
    fmt.Println("1-这是一个中间件")
    ctx.Next()
    fmt.Println("2-这是一个中间件")
    end := time.Now().UnixNano()
    fmt.Println(end - start)
}
func initMiddleware2(ctx *gin.Context) {
    start := time.Now().UnixNano()
    fmt.Println("1-这是一个中间件")
    ctx.Next()
    fmt.Println("2-这是一个中间件")
    end := time.Now().UnixNano()
    fmt.Println(end - start)
}


func main() {
    r := gin.Default()
    // 自定义函数要放在加载模板前面
    r.SetFuncMap(template.FuncMap{
        "UnixToTime": UnixToTime,
    })
    // 加载模板
    r.LoadHTMLGlob("templates/**/*")


    // 配置静态web目录 第一个参数表示路由,第二个参数表示映射目录
    r.Static("/static", "./static")


    //Get 请求传值
    r.GET("/", initMiddleware1, initMiddleware2, func(ctx *gin.Context) {
        fmt.Println("这是一个首页")
        ctx.String(200, "gin首页")
    })
    r.GET("/news", func(ctx *gin.Context) {
        ctx.String(200, "新闻页面")
    })
    r.GET("/login", func(ctx *gin.Context) {
        ctx.String(200, "login")
    })
    r.Run()
}

全局中间件

r.Use()

package main


import (
    "fmt"
    "text/template"
    "time"


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


type Article struct {
    Title   string
    Content string
}


type UserInfo struct {
    Username string `json:"username" form:"username"`
    Password string `json:"password" form:"password"`
}


func UnixToTime(timestamp int) string {
    fmt.Println(timestamp)
    t := time.Unix(int64(timestamp), 0)
    return t.Format("2006-01-02 15:04:05")
}


func initMiddleware1(ctx *gin.Context) {
    start := time.Now().UnixNano()
    fmt.Println("1-这是一个中间件")
    ctx.Next()
    fmt.Println("2-这是一个中间件")
    end := time.Now().UnixNano()
    fmt.Println(end - start)
}
func initMiddleware2(ctx *gin.Context) {
    start := time.Now().UnixNano()
    fmt.Println("1-这是一个中间件")
    ctx.Next()
    fmt.Println("2-这是一个中间件")
    end := time.Now().UnixNano()
    fmt.Println(end - start)
}


func main() {
    r := gin.Default()
    // 自定义函数要放在加载模板前面
    r.SetFuncMap(template.FuncMap{
        "UnixToTime": UnixToTime,
    })
    // 加载模板
    r.LoadHTMLGlob("templates/**/*")


    // 配置静态web目录 第一个参数表示路由,第二个参数表示映射目录
    r.Static("/static", "./static")


    r.Use(initMiddleware1, initMiddleware2)


    //Get 请求传值
    r.GET("/", func(ctx *gin.Context) {
        fmt.Println("这是一个首页")
        ctx.String(200, "gin首页")
    })
    r.GET("/news", func(ctx *gin.Context) {
        ctx.String(200, "新闻页面")
    })
    r.GET("/login", func(ctx *gin.Context) {
        ctx.String(200, "login")
    })


    r.Run()
}

分组路由配置中间件

package middlewares


import (
    "fmt"
    "time"


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


func InitMiddleware(ctx *gin.Context) {
    fmt.Println(time.Now())


    fmt.Println(ctx.Request.URL)
}
package routers

import (
    "gin_07/controllers/admin"
    "gin_07/middlewares"


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


func AdminRoutersInit(r *gin.Engine) {
    adminRouters := r.Group("/admin", middlewares.InitMiddleware)
    adminRouters.Use()
    {
        adminRouters.GET("/", admin.IndexController{}.Index)
        adminRouters.GET("/user", admin.UserController{}.Index)
        adminRouters.GET("/user/add", admin.UserController{}.Add)
        adminRouters.GET("/user/edit", admin.UserController{}.Edit)
        adminRouters.GET("/article", admin.ArticleController{}.Index)
        adminRouters.GET("/article/add", admin.ArticleController{}.Add)
        adminRouters.GET("/article/edit", admin.ArticleController{}.Edit)


    }
}

中间件和对应控制器之间共享数据

设置值:ctx.Set{""}

获取值:username,_:=ctx.Get("username")

package middlewares


import (
    "fmt"
    "time"


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


func InitMiddleware(ctx *gin.Context) {
    fmt.Println(time.Now())


    fmt.Println(ctx.Request.URL)


    ctx.Set("username", "张三")
}
package admin


import (
    "fmt"
    "net/http"


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


type IndexController struct {
}


func (con IndexController) Index(ctx *gin.Context) {
    username, _ := ctx.Get("username")
    fmt.Println(username)
    v, ok := username.(string)
    if ok {
        ctx.String(http.StatusOK, "用户列表--"+v)
    } else {
        ctx.String(http.StatusOK, "用户列表--获取用户失败")
    }
}

中间件中使用goroutine

当在中间件或hander中启动新的goroutine时,不能使用原始的上下文,

package middlewares


import (
    "fmt"
    "time"


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


func InitMiddleware(ctx *gin.Context) {
    fmt.Println(time.Now())


    fmt.Println(ctx.Request.URL)


    ctx.Set("username", "张三")


    // 定义一个goroutine统计日志
    cCp := ctx.Copy()
    go func() {
        time.Sleep(2 * time.Second)
        fmt.Println("Done! in path" + cCp.Request.URL.Path)
    }()
}

Gin中自定义Model

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

package models


import (
    "fmt"
    "time"
)


func UnixToTime(timestamp int) string {
    fmt.Println(timestamp)
    t := time.Unix(int64(timestamp), 0)
    return t.Format("2006-01-02 15:04:05")
}
package qiantai


import (
    "net/http"


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


type DefaultController struct {
}


func (con DefaultController) Index(ctx *gin.Context) {
    ctx.HTML(http.StatusOK, "default/index.html", gin.H{
        "msg": "我是一个msg",
        "t":   167988418,
    })
}
func (con DefaultController) News(ctx *gin.Context) {
    ctx.String(http.StatusOK, "新闻")
}

Gin文件上传

{{define "admin/useradd.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>
    <h2>文件上传</h2>


    <form action="/admin/user/doUpload" 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}}
package admin


import (
    "net/http"
    "path"


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


type UserController struct {
    BaseController
}


func (con UserController) Index(ctx *gin.Context) {
    // ctx.String(http.StatusOK, "用户列表")
    con.success(ctx)
}
func (con UserController) Add(ctx *gin.Context) {
    ctx.HTML(http.StatusOK, "admin/useradd.html", gin.H{})
}
func (con UserController) Edit(ctx *gin.Context) {
    ctx.String(http.StatusOK, "修改用户")
}


func (con UserController) DoUpload(ctx *gin.Context) {
    username := ctx.PostForm("username")


    file, err := ctx.FormFile("face")


    // file.Filename 获取文件名称
    dst := path.Join("./static/upload", file.Filename)
    if err == nil {
        ctx.SaveUploadedFile(file, dst)
    }
    ctx.JSON(http.StatusOK, gin.H{
        "success":  true,
        "username": username,
        "dst":      dst,
    })
}

相同名字的多个文件上传

{{define "admin/useradd.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>
    <h2>文件上传</h2>


    <form action="/admin/user/doUpload" 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>
        头像3:<input type="file" name="face[]" />
        <br><br>
        头像4:<input type="file" name="face[]" />
        <br><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>
{{end}}
package admin


import (
    "net/http"
    "path"


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


type UserController struct {
    BaseController
}


func (con UserController) Index(ctx *gin.Context) {
    // ctx.String(http.StatusOK, "用户列表")
    con.success(ctx)
}
func (con UserController) Add(ctx *gin.Context) {
    ctx.HTML(http.StatusOK, "admin/useradd.html", gin.H{})
}
func (con UserController) Edit(ctx *gin.Context) {
    ctx.String(http.StatusOK, "修改用户")
}


func (con UserController) DoUpload(ctx *gin.Context) {
    username := ctx.PostForm("username")


    form, _ := ctx.MultipartForm()
    file := form.File["face[]"]


    for _, file := range file {
        // file.Filename 获取文件名称
        dst := path.Join("./static/upload", file.Filename)
        ctx.SaveUploadedFile(file, dst)
    }
    ctx.JSON(http.StatusOK, gin.H{
        "success":  true,
        "username": username,
    })
}

文件上传 按照日期存储

package admin


import (
    "fmt"
    "gin_07/models"
    "net/http"
    "os"
    "path"
    "strconv"


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


type UserController struct {
    BaseController
}


func (con UserController) Index(ctx *gin.Context) {
    // ctx.String(http.StatusOK, "用户列表")
    con.success(ctx)
}
func (con UserController) Add(ctx *gin.Context) {
    ctx.HTML(http.StatusOK, "admin/useradd.html", gin.H{})
}
func (con UserController) Edit(ctx *gin.Context) {
    ctx.String(http.StatusOK, "修改用户")
}


// func (con UserController) DoUpload(ctx *gin.Context) {
//  username := ctx.PostForm("username")


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


//      for _, file := range file {
//          // file.Filename 获取文件名称
//          dst := path.Join("./static/upload", file.Filename)
//          ctx.SaveUploadedFile(file, dst)
//      }
//      ctx.JSON(http.StatusOK, gin.H{
//          "success":  true,
//          "username": username,
//      })
//  }
func (con UserController) DoUpload(ctx *gin.Context) {
    username := ctx.PostForm("username")
    // 1、 获取上传的文件
    file, err := ctx.FormFile("face")


    if err == nil {
        // 2、获取后缀名 判断类型是否正确
        extName := path.Ext(file.Filename)


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


        if _, ok := allowExtMap[extName]; !ok {
            ctx.String(http.StatusOK, "上传的文件类型不合法")
            return
        }


        // 3、创建图片保存目录
        day := models.GetDay()
        dir := "./static/upload/" + day


        err := os.MkdirAll(dir, 0666)
        if err != nil {
            fmt.Println(err)
            ctx.String(http.StatusOK, "上传的文件不合法")
            return
        }
        // 4、生成文件名称和文件保存的目录
        filename := strconv.FormatInt(models.GetUnix(), 10) + extName


        // 5、执行上传
        dst := path.Join(dir, filename)
        ctx.SaveUploadedFile(file, dst)
    }
    ctx.JSON(http.StatusOK, gin.H{
        "success":  true,
        "username": username,
    })
}

Gin中的Cookie

package qiantai


import (
    "net/http"


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


type DefaultController struct {
}


func (con DefaultController) Index(ctx *gin.Context) {
    // 设置cookie
    ctx.SetCookie("username", "张三", 3600, "/", "localhost", false, true)


    ctx.SetCookie("hobby", "李四", 5, "/", "localhost", false, true)


    ctx.HTML(http.StatusOK, "default/index.html", gin.H{
        "msg": "我是一个msg",
        "t":   167988418,
    })
}
func (con DefaultController) News(ctx *gin.Context) {
    username, _ := ctx.Cookie("username")
    hobby, _ := ctx.Cookie("hobby")
    ctx.String(http.StatusOK, "username=%v-----hobby=%v", username, hobby)
}
func (con DefaultController) Shop(ctx *gin.Context) {
    username, _ := ctx.Cookie("username")
    ctx.String(http.StatusOK, "cookie="+username)
}
func (con DefaultController) DeleteCookie(ctx *gin.Context) {
    // 设置cookie
    ctx.SetCookie("username", "张三", -1, "/", "localhost", false, true)
    ctx.String(http.StatusOK, "删除成功")
}

Gin中的session

package main


import (
    "gin_07/models"
    "gin_07/routers"
    "text/template"


    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/cookie"
    "github.com/gin-gonic/gin"
)


func main() {
    // 初始化路由
    r := gin.Default()


    //自定义模板函数
    r.SetFuncMap(template.FuncMap{
        "UnixToTime": models.UnixToTime,
    })


    // 配置模板文件
    r.LoadHTMLGlob("templates/**/*")


    // 配置静态web目录 第一个参数表示路由,第二个参数表示映射目录
    r.Static("/static", "./static")


    // 创建基于cookie的存储引擎
    store := cookie.NewStore([]byte("secret123"))
    // 设置session中间件,参数mysession,指的是session的名字,也是cookie的名字
    r.Use(sessions.Sessions("mysession", store))


    routers.DefaultRoutersInit(r)


    routers.ApiRoutersInit(r)


    routers.AdminRoutersInit(r)


    r.Run()
}
package qiantai


import (
    "net/http"


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


type DefaultController struct {
}


func (con DefaultController) Index(ctx *gin.Context) {
    session := sessions.Default(ctx)
    session.Set("username", "张三 111")
    session.Save()


    ctx.HTML(http.StatusOK, "default/index.html", gin.H{
        "msg": "我是一个msg",
        "t":   167988418,
    })
}
func (con DefaultController) News(ctx *gin.Context) {
    session := sessions.Default(ctx)
    username := session.Get("username")
    ctx.String(http.StatusOK, "username=%v", username)
}

session存储到redis

package main


import (
    "gin_07/models"
    "gin_07/routers"
    "text/template"


    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/redis"
    "github.com/gin-gonic/gin"
)


func main() {
    // 初始化路由
    r := gin.Default()


    //自定义模板函数
    r.SetFuncMap(template.FuncMap{
        "UnixToTime": models.UnixToTime,
    })


    // 配置模板文件
    r.LoadHTMLGlob("templates/**/*")


    // 配置静态web目录 第一个参数表示路由,第二个参数表示映射目录
    r.Static("/static", "./static")


    store, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("secret123"))
    r.Use(sessions.Sessions("mysession", store))


    routers.DefaultRoutersInit(r)


    routers.ApiRoutersInit(r)


    routers.AdminRoutersInit(r)


    r.Run()
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值