路由分组与抽离
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()
}