gin學習

gin學習筆記,不僅包含了基本的增刪查改外,還包括參數傳遞,上傳下載,模版、session與中間件等,方便收藏自習可用

文章目錄

  • 獲得個請求
  • get打印字符串
  • get請求xml
  • get請求跳轉
  • http方法
  • 路由
  • 可以通過Context的Param方法來獲取API參數
  • 可以通過DefaultQuery()或Query()方法獲取
  • 可以通過GetQuery()與Query()方法獲取
  • 可以通過BindQuery
  • 可以通過shouldBindQuery()傳遞
  • QueryMap進行參數傳遞
  • 結構體有map進行傳遞
  • 表單參數傳遞
  • 路徑參數傳遞
  • 上傳一個文件
    • 上傳特定文件
    • 上傳多個文件
  • 上傳,對文件進行保存
    • routes group
    • 404 not found
    • json數據解析和綁定
    • 表單數據解析和綁定
    • url數據綁定
    • 各種數據格式的響應
  • html模板渲染
  • 靜態資源文件進行渲染
  • 模版取消轉義
  • go重定向
  • cookie
  • 多session
  • redis Session固化存儲
  • 異步執行與同步執行
  • 中間件
  • 全局中間件
  • 局部中間件
    • 定義兩個路由,計算執行時間
    • cookie的使用
    • Cookie練習
    • 結構體驗證
    • 結構體

獲得個請求

package mainimport "github.com/gin-gonic/gin"func main() {r := gin.Default()//r.Get("/hello")r.GET("/", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello world",})})err := r.Run(":8080")if err != nil {panic(err)}
}

get打印字符串

type User struct {Id         int64             `form:"id" json:"id" uri:"id"`Name       string            `form:"name" json:"name" uri:"name"`Address    []string          `form:"address" binding:"required" json:"address" uri:"address"`AddressMap map[string]string `form:"addressMap" json:"addressMap" uri:"addressMap"`
}func main() {r := gin.Default()r.GET("/user/save", func(c *gin.Context) {c.String(http.StatusOK, "this is %s", "ms string value")})r.Run(":8081")
}

get請求xml

type User struct {Id         int64             `form:"id" json:"id" uri:"id" xml:"id"`Name       string            `form:"name" json:"name" uri:"name" xml:"name"`Address    []string          `form:"address" binding:"required" json:"address" uri:"address" xml:"address"`AddressMap map[string]string `form:"addressMap" json:"addressMap" uri:"addressMap" xml:"addressMap"`
}func main() {r := gin.Default()r.GET("/user/save", func(c *gin.Context) {id := c.Query("id")name := c.Query("name")c.XML(http.StatusOK, gin.H{"id": id, "message": name})})r.Run(":8081")
}

get請求跳轉

http方法

  • GET :get方法請求一個指定資源的表示形式,或使用GET請求應該只被用于獲取數據
  • POST :POST方法用于將實體提交到指定資源,通常會導致在服務器上的狀態變化
  • HEAD:HEAD方法請求一個與GET請求的響應相同的響應,但沒有響應體
  • PUT:PUT方法用請求有效載荷替換目標資源的所有當前表示
  • DELETE : DELETE 方法刪除指定的資源

路由

func main() {r := gin.Default()//r.Get("/hello")r.GET("/", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello world",})})r.GET("/get", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello world",})})r.POST("/save", func(c *gin.Context) {c.JSON(200, gin.H{"message": "save",})})r.PUT("/put", func(c *gin.Context) {c.JSON(200, gin.H{"message": "put",})})r.DELETE("/delete", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello DELETE",})})r.Any("/Any", func(c *gin.Context) {c.JSON(200, gin.H{"message": "hello Any",})})r.GET("/user/find/:id", func(ctx *gin.Context) {ctx.JSON(200, ctx.Param("id"))})r.GET("/u/*Path", func(ctx *gin.Context) {ctx.JSON(200, ctx.Param("Path"))})v1 := r.Group("/v1"){v1.GET("find", func(ctx *gin.Context) {ctx.JSON(200, gin.H{"message": "find",})})}v2 := r.Group("/v2"){v2.GET("find", func(ctx *gin.Context) {ctx.JSON(200, gin.H{"message": "find",})})}err := r.Run(":8080")if err != nil {panic(err)}
}

可以通過Context的Param方法來獲取API參數

func main() {r := gin.Default()r.GET("/user/:name/*action", func(c *gin.Context) {name := c.Param("name")action := c.Param("action")action = strings.Trim(action, "/")c.String(http.StatusOK, name+"is "+action)})//r.POST("/xxxpost", getting)r.Run(":8000")
}

可以通過DefaultQuery()或Query()方法獲取

傳個localhost:8080/user?name=zhangsan

func main() {r := gin.Default()r.GET("/user", func(c *gin.Context) {name := c.DefaultQuery("name", "枯藤")c.String(http.StatusOK, "Hello %s", name)})r.Run(":8080")
}

可以通過GetQuery()與Query()方法獲取

func main() {r := gin.Default()//r.Get("/hello")r.GET("/user/save", func(c *gin.Context) {id := c.Query("id")name := c.Query("name")addr, ok := c.GetQuery("addr")c.JSON(200, gin.H{"id":   id,"name": name,"addr": addr,"errs": ok,})})err := r.Run(":8080")if err != nil {panic(err)}
}

可以通過BindQuery

type User struct {Id   int64  `form:"id"`Name string `form:"name"`
}func main() {r := gin.Default()//r.Get("/hello")r.GET("/user/save", func(c *gin.Context) {var user Usererr := c.BindQuery(&user)if err != nil {log.Fatalln(err)}c.JSON(http.StatusOK, user)})errs := r.Run(":8080")if errs != nil {panic(errs)}
}

可以通過shouldBindQuery()傳遞

type User struct {Id      int64    `form:"id"`Name    string   `form:"name"`Address []string `form:"address" binding:"required"`
}func main() {r := gin.Default()//r.Get("/hello")r.GET("/user/save", func(c *gin.Context) {var user Userc.ShouldBindQuery(&user)c.JSON(http.StatusOK, user)})errs := r.Run(":8080")if errs != nil {panic(errs)}
}

QueryMap進行參數傳遞

type User struct {Id      int64    `form:"id"`Name    string   `form:"name"`Address []string `form:"address" binding:"required"`
}func main() {r := gin.Default()//r.Get("/hello")r.GET("/user/save", func(c *gin.Context) {addressMap := c.QueryMap("addressMap")c.JSON(200, addressMap)})errs := r.Run(":8080")if errs != nil {panic(errs)}
}
localhost:8080/user/save?addressMap[c]=d&addressMap[d]=a
{"c": "d","d": "a"
}

結構體有map進行傳遞

type User struct {Id         int64             `form:"id"`Name       string            `form:"name"`Address    []string          `form:"address" binding:"required"`AddressMap map[string]string `form:"addressMap"`
}func main() {r := gin.Default()//r.Get("/hello")r.GET("/user/save", func(c *gin.Context) {var user Userc.ShouldBind(&user)user.AddressMap = c.QueryMap("addressMap")c.JSON(200, user)})_ = r.Run(":8080")}

表單參數傳遞

<!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>Document</title>
</head>
<body>
<form action="http://localhost:8080/form" method="post" action="application/x-www-form-urlencoded">用戶名:<input type="text" name="username" placeholder="請輸入你的用戶
名">  <br>&nbsp;&nbsp;&nbsp;碼:<input type="password" name="userpassword" placeholder="請輸入你的密碼">  <br><input type="submit" value="提交">
</form>
</body>
</html>

用一個表單進行參數傳遞

func main() {r := gin.Default()r.POST("/form", func(c *gin.Context) {types := c.DefaultPostForm("type", "post")username := c.PostForm("username")password := c.PostForm("userpassword")c.String(http.StatusOK, fmt.Sprintf("username:%s,password:%s,type:%s", username, password, types))})r.Run(":8080")
}

關于表單的其他參數

type User struct {Id         int64             `form:"id"`Name       string            `form:"name"`Address    []string          `form:"address" binding:"required"`AddressMap map[string]string `form:"addressMap"`
}func main() {r := gin.Default()//r.Get("/hello")r.POST("/user/save", func(c *gin.Context) {id := c.PostForm("id")name := c.PostForm("name")address := c.PostFormArray("address")addressMap := c.PostFormMap("addressMap")c.JSON(200, gin.H{"code":         200,"msg":          "success","id":           id,"name":         name,"addressMap":   addressMap,"addressSlice": address,})})r.Run(":8081")}

也可以用綁定獲取表單傳過來的參數

type User struct {Id         int64             `form:"id"`Name       string            `form:"name"`Address    []string          `form:"address" binding:"required"`AddressMap map[string]string `form:"addressMap"`
}func main() {r := gin.Default()//r.Get("/hello")r.POST("/user/save", func(c *gin.Context) {var user Userc.ShouldBind(&user)addressMap := c.PostFormMap("addressMap")user.AddressMap = addressMapc.JSON(200, user)})r.Run(":8081")}

也可以用json形式

type User struct {Id         int64             `form:"id" json:"id"`Name       string            `form:"name" json:"name"`Address    []string          `form:"address" binding:"required" json:"address"`AddressMap map[string]string `form:"addressMap" json:"addressMap"`
}func main() {r := gin.Default()r.POST("/user/save", func(c *gin.Context) {var user Userc.ShouldBindJSON(&user)c.JSON(200, user)})r.Run(":8081")
}

路徑參數傳遞

在這里插入代碼片

上傳一個文件

<!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>Document</title>
</head>
<body>
<form action="http://localhost:8080/upload" method="POST" enctype="multipart/form-data"><input type="file" name="file" /><button type="submit">上傳</button>
</form>
</body>
</html>

go代碼


func main() {r := gin.Default()r.MaxMultipartMemory = 8 << 20 // 8 MBr.POST("/upload", func(c *gin.Context) {file, err := c.FormFile("file")if err != nil {log.Printf("上傳文件時發生錯誤: %v", err)c.String(500, "上傳圖片出錯: %v", err)return}// 檢查文件類型if !strings.HasPrefix(file.Header.Get("Content-Type"), "image/") {c.String(400, "只允許上傳圖片文件")return}// 確保上傳目錄存在if err := os.MkdirAll("./uploads", os.ModePerm); err != nil {log.Printf("創建文件夾失敗: %v", err)c.String(500, "創建文件夾失敗: %v", err)return}// 保存文件savePath := "./uploads/" + file.Filenameif err := c.SaveUploadedFile(file, savePath); err != nil {log.Printf("保存文件時發生錯誤: %v", err)c.String(500, "保存文件出錯: %v", err)return}c.String(http.StatusOK, "文件上傳成功: %s", file.Filename)})r.Run(":8080")
}

上傳特定文件

func main() {r := gin.Default()r.POST("/upload", func(c *gin.Context) {_, headers, err := c.Request.FormFile("file")if err != nil {log.Printf("Error when try yo get file:%v", err)}if headers.Size > 1024*1024*2 {fmt.Println("文件太大了...")return}if headers.Header.Get("Content-Type") != "image/png" {fmt.Println("只允許上傳png圖片")return}c.SaveUploadedFile(headers, "./video/"+headers.Filename)c.String(http.StatusOK, headers.Filename)})r.Run(":8080")
}

上傳多個文件

func main() {r := gin.Default()r.MaxMultipartMemory = 8 << 20r.POST("/upload", func(c *gin.Context) {form, err := c.MultipartForm()if err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("get error: %s", err.Error()))}//獲取所有圖片files := form.File["files"]//遍歷所有圖片for _, file := range files {if err := c.SaveUploadedFile(file, file.Filename); err != nil {c.String(http.StatusBadRequest, fmt.Sprintf("upload error:%s", err.Error()))return}}c.String(200, fmt.Sprintf("upload ok %d files", len(files)))})r.Run(":8000")
}

上傳,對文件進行保存

type User struct {Id         int64             `form:"id" json:"id" uri:"id"`Name       string            `form:"name" json:"name" uri:"name"`Address    []string          `form:"address" binding:"required" json:"address" uri:"address"`AddressMap map[string]string `form:"addressMap" json:"addressMap" uri:"addressMap"`
}func main() {r := gin.Default()r.POST("/user/save/:id/:name", func(c *gin.Context) {form, err := c.MultipartForm()if err != nil {panic(err)}value := form.Valuefiles := form.Filefor _, fileArray := range files {for _, f := range fileArray {c.SaveUploadedFile(f, "./"+f.Filename)}}c.JSON(200, value)})r.Run(":8081")
}

routes group

路由組合

func main() {r := gin.Default()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(":8080")
}func login(c *gin.Context) {name := c.DefaultQuery("name", "jack")c.String(200, fmt.Sprintf("hello %s %s\n", name, name))
}func submit(c *gin.Context) {name := c.DefaultQuery("name", "lily")c.String(200, fmt.Sprintf("hello %s %s\n", name, name))
}

404 not found

func main() {r := gin.Default()r.GET("/user", func(c *gin.Context) {name := c.DefaultQuery("name", "枯藤")c.String(http.StatusOK, fmt.Sprintf("hello %s", name))})r.NoRoute(func(c *gin.Context) {c.String(http.StatusNotFound, "404 page not found222222222222")})r.Run(":8080")}

json數據解析和綁定


type Login struct {User     string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`Password string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}func main() {//創建路由r := gin.Default()//json綁定r.POST("loginJSON", func(c *gin.Context) {var json Loginif err := c.ShouldBindJSON(&json); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}if json.User != "root" || json.Password != "123456" {c.JSON(http.StatusBadRequest, gin.H{"status": "304"})return}c.JSON(http.StatusOK, gin.H{"status": "200"})})r.Run(":8080")
}

表單數據解析和綁定


type Login struct {User     string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`Password string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}func main() {//創建路由r := gin.Default()r.POST("/loginForm", func(c *gin.Context) {var form Loginif err := c.Bind(&form); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}if form.User != "root" || form.Password != "admin" {c.JSON(http.StatusBadRequest, gin.H{"error": "304"})return}c.JSON(http.StatusOK, gin.H{"status": "200"})})r.Run(":8080")}

url數據綁定

type Login struct {User     string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`Password string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}func main() {r := gin.Default()//json綁定r.GET("/:user/:password", func(c *gin.Context) {var login Loginif err := c.ShouldBindUri(&login); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}//判斷用戶名密碼是否正確if login.User != "root" || login.Password != "123456" {c.JSON(http.StatusBadRequest, gin.H{"error": "304"})return}c.JSON(http.StatusOK, gin.H{"message": "200"})})r.Run(":8080")}

各種數據格式的響應

func main() {//創建路由r := gin.Default()//1.jsonr.GET("/someJSON", func(c *gin.Context) {c.JSON(200, gin.H{"message": "someJSON", "status": 200})})//結構體響應r.GET("/someStruct", func(c *gin.Context) {var msg struct {Name    stringMessage stringNumber  int}msg.Name = "root"msg.Message = "message"msg.Number = 124c.JSON(200, msg)})r.GET("/someXML", func(c *gin.Context) {c.XML(200, gin.H{"message": "abc"})})//yaml響應r.GET("/someYAML", func(c *gin.Context) {c.YAML(200, gin.H{"message": "zhangsan"})})//5. protobuf 格式r.GET("/someProtobuf", func(c *gin.Context) {reps := []int64{int64(1), int64(2)}label := "label"data := &protoexample.Test{Label: &label,Reps:  reps,}c.ProtoBuf(200, data)})r.Run(":8080")
}

html模板渲染

目錄:
在這里插入圖片描述

func main() {//創建路由r := gin.Default()r.LoadHTMLGlob("tem/*")r.GET("/", func(c *gin.Context) {c.HTML(http.StatusOK, "index.html", gin.H{"title": "我是測試","ce":    "123456",})})r.Run(":8080")}

在這里插入圖片描述

{{ define "user/index.html" }}
<!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>
fgkjdskjdsh{{.address}}
</body>
</html>
{{ end }}
func main() {//創建路由r := gin.Default()r.LoadHTMLGlob("tem/**/*")r.GET("/index", func(c *gin.Context) {c.HTML(http.StatusOK, "user/index.html", gin.H{"title":   "我是測試","address": "www.61mh.com",})})r.Run(":8080")}

模板嵌套
header.html

{{define "public/header"}}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>{{.title}}</title>
</head>
<body>{{end}}

footer.html

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

index.html

{{ define "user/index.html" }}
{{template "public/header" .}}
fgkjdskjdsh{{.address}}
{{template "public/footer" .}}
{{ end }}
func main() {//創建路由r := gin.Default()r.LoadHTMLGlob("tem/**/*")r.GET("/index", func(c *gin.Context) {c.HTML(http.StatusOK, "user/index.html", gin.H{"title":   "Goland Projects","address": "www.51mh.com",})})r.Run(":8080")}

靜態資源文件進行渲染


func main() {r := gin.Default()//r.LoadHTMLFiles("./templates/index.tmpl", "./templates/user.tmpl")r.SetFuncMap(template.FuncMap{"safe": func(str string) template.HTML {return template.HTML(str)},})r.Static("/css", "./templates/css")r.LoadHTMLGlob("templates/**/*")r.GET("/index", func(c *gin.Context) {c.HTML(http.StatusOK, "index.tmpl", gin.H{"title": "<a href='http://www.baidu.com'>hello template</a>",})})r.GET("/user", func(c *gin.Context) {c.HTML(http.StatusOK, "user.tmpl", gin.H{"title": "<a href='http://www.baidu.com'>hello template</a>",})})r.Run(":8081")
}

模版取消轉義

package mainimport ("github.com/gin-gonic/gin""html/template""net/http"
)func main() {r := gin.Default()//r.LoadHTMLFiles("./templates/index.tmpl", "./templates/user.tmpl")r.SetFuncMap(template.FuncMap{"safe": func(str string) template.HTML {return template.HTML(str)},})r.LoadHTMLGlob("templates/**/*")r.GET("/index", func(c *gin.Context) {c.HTML(http.StatusOK, "index.tmpl", gin.H{"title": "<a href='http://www.baidu.com'>hello template</a>",})})r.GET("/user", func(c *gin.Context) {c.HTML(http.StatusOK, "user.tmpl", gin.H{"title": "<a href='http://www.baidu.com'>hello template</a>",})})r.Run(":8081")
}

go重定向

func main() {//創建路由r := gin.Default()r.GET("/index", func(c *gin.Context) {c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com")})r.Run(":8080")
}

cookie

設置cookie

c.SetCookie("site_cookie", "123456", 60*60*24, "/", "", false, false)

刪除cookie

c.SetCookie("site_cookie", "123456", -1, "/", "", false, false)

讀取cookie

data, err := c.Cookie("site_cookie")if err != nil {log.Println(err)c.JSON(200, err.Error())return}c.JSON(200, data)

多session

func main() {r := gin.Default()store := cookie.NewStore([]byte("secret"))sessionNames := []string{"a", "b"}r.Use(sessions.SessionsMany(sessionNames, store))r.GET("/hello", func(c *gin.Context) {sessionA := sessions.DefaultMany(c, "a")sessionB := sessions.DefaultMany(c, "b")if sessionA.Get("name") == nil {sessionA.Set("name", "b")sessionA.Save()}if sessionB.Get("name") == nil {sessionB.Set("name", "c")sessionB.Save()}})r.Run(":8081")
}

redis Session固化存儲

func main() {r := gin.Default()store, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("secret"))r.Use(sessions.Sessions("mysession", store))r.GET("/incr", func(c *gin.Context) {session := sessions.Default(c)var cnt intv := session.Get("count")if v == nil {cnt = 0} else {cnt = v.(int)cnt++}session.Set("count", cnt)session.Save()c.JSON(200, gin.H{"count": cnt,})})r.Run(":8080")

異步執行與同步執行

func main() {//創建路由r := gin.Default()//異步r.GET("/long_async", func(c *gin.Context) {//一個副本copyContext := c.Copy()go func() {time.Sleep(3 * time.Second)log.Println("異步執行:" + copyContext.Request.URL.Path)}()})//同步r.GET("/long_sync", func(c *gin.Context) {time.Sleep(3 * time.Second)log.Println("同步執行:" + c.Request.URL.Path)})r.Run(":8080")
}

中間件

在gin框架中,中間件是指可以攔截http請求-響應生命周期的特殊函數,在請求-響應生命周期中可以注冊多個中間件,每個中間件執行不同的功能,一個中間件執行完再輪到下一個中間件執行。

全局中間件

func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()fmt.Println("中間件開始執行了")c.Set("request", "中間件")status := c.Writer.Status()fmt.Println("中間件執行完畢", status)t2 := time.Since(t)fmt.Println("time:", t2)}
}func main() {r := gin.Default()//注冊中間價r.Use(MiddleWare())//{}代碼規范{r.GET("/ce", func(c *gin.Context) {req, _ := c.Get("request")fmt.Println("request:", req)c.JSON(200, gin.H{"request": req})})}r.Run(":8080")
}

局部中間件


func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()fmt.Println("中間開始執行了")c.Set("request", "中間劍")c.Next()status := c.Writer.Status()fmt.Println("中間件執行完畢", status)t2 := time.Since(t)fmt.Println("time:", t2)}
}func main() {r := gin.Default()r.Use(MiddleWare()){r.GET("/ce", func(c *gin.Context) {req, _ := c.Get("request")fmt.Println("request:", req)c.JSON(200, gin.H{"request": req})})}r.Run(":8080")
}

定義兩個路由,計算執行時間


func myTime(c *gin.Context) {start := time.Now()c.Next()since := time.Since(start)fmt.Println("程序用時:", since)
}func main() {r := gin.Default()//注冊中間件r.Use(myTime)shoppingGroup := r.Group("/shopping"){shoppingGroup.GET("/index", shopIndexHandler)shoppingGroup.GET("/home", shopHomeHandler)}r.Run(":8080")}func shopIndexHandler(c *gin.Context) {time.Sleep(5 * time.Second)
}func shopHomeHandler(c *gin.Context) {time.Sleep(3 * time.Second)fmt.Println("how do you do?")
}

cookie的使用

func main() {r := gin.Default()r.GET("/cookie", func(c *gin.Context) {cookie, err := c.Cookie("key_code")if err != nil {cookie = "ThisIsCookie"c.SetCookie("key_code", "value_cookie", 60, "/","localhost", false, true)}fmt.Printf("cookie的值是:%s\n", cookie)})r.Run(":8080")
}

Cookie練習

func AuthMiddleWare() gin.HandlerFunc {return func(c *gin.Context) {if cookie, err := c.Request.Cookie("username"); err == nil {if cookie.String() == "123" {c.Next()return}}c.JSON(http.StatusUnauthorized, gin.H{"error": "error"})c.Abort()return}
}
func main() {r := gin.Default()r.GET("/login", func(c *gin.Context) {c.SetCookie("abc", "123", 60, "/", "localhost", false, true)c.String(200, "Login Success!")})r.GET("/home", AuthMiddleWare(), func(c *gin.Context) {c.JSON(200, gin.H{"data": "home"})})r.Run(":8080")
}

結構體驗證

type Person struct {Age      int       `form:"age" binding:"required,gt=10"`Name     string    `form:"name" binding:"required"`Birthday time.Time `form:"birthday" time_format:"2006-01-02"` time_utc: "1"
}func main() {r := gin.Default()r.GET("/51mh", func(c *gin.Context) {var person Personif err := c.ShouldBind(&person); err != nil {c.String(500, fmt.Sprint(err))return}c.String(200, fmt.Sprintf("%#v", person))})r.Run(":8080")
}

結構體


type Login struct {User     string `uri:"user" validate:"checkName"`Password string `uri:"password"`
}func checkName(f1 validator.FieldLevel) bool {if f1.Field().String() != "root" {return false}return true
}func main() {r := gin.Default()validate := validator.New()r.GET("/:user/:password", func(c *gin.Context) {var login Loginerr := validate.RegisterValidation("checkName", checkName)if err := c.ShouldBindUri(&login); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}err = validate.Struct(login)if err != nil {for _, err := range err.(validator.ValidationErrors) {fmt.Println(err)}return}fmt.Println("success")})r.Run(":8080")}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/73305.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73305.shtml
英文地址,請注明出處:http://en.pswp.cn/web/73305.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Flutter運行錯誤:UG! exception in phase ‘semantic analysis‘

最近在Mac Mini M4上通過Android Studio導入Flutter項目并運行&#xff0c;結果一直跑不起來&#xff0c;錯誤日志如下&#xff1a; 執行命令查看版本信息&#xff1a; flutter doctor --verbose通過輸出信息Java version OpenJDK Runtime Environment (build 21.0.41242208…

【計算機網絡運輸層詳解】

文章目錄 一、前言二、運輸層的功能1. 端到端通信2. 復用與分用3. 差錯檢測4. 流量控制5. 擁塞控制 三、運輸層協議&#xff1a;TCP 和 UDP1. TCP&#xff1a;面向連接的可靠傳輸協議2. UDP&#xff1a;無連接的傳輸協議 四、端口號與進程通信1. 端口號分類2. 端口通信模型 五、…

51單片機和STM32 入門分析

51單片機和STM32是嵌入式開發中兩種主流的微控制器&#xff0c;它們在架構、性能、應用場景等方面存在顯著差異。以下是兩者的對比分析及選擇建議&#xff1a; 1. 51單片機與STM32的定義與特點 51單片機 定義&#xff1a;基于Intel 8051內核的8位微控制器&#xff0c;結構簡單…

開源視覺語言模型MiniMax-VL-01:動態分辨率+4M超長文本,性能比肩GPT-4o

在人工智能領域&#xff0c;構建能夠像人類一樣理解、思考和行動的智能體&#xff08;AI Agent&#xff09;一直是研究人員的終極目標之一。而實現這一目標的關鍵在于模型是否具備足夠強大的感知能力、記憶能力和推理能力。近期&#xff0c;國內人工智能公司MiniMax重磅開源了其…

excel 列單元格合并(合并列相同行)

代碼 首先自定義注解CellMerge&#xff0c;用于標記哪些屬性需要合并&#xff0c;哪個是主鍵**&#xff08;這里做了一個優化&#xff0c;可以標記多個主鍵&#xff09;** import org.dromara.common.excel.core.CellMergeStrategy;import java.lang.annotation.*;/*** excel…

flowable適配達夢7 (2.1)

經過第一版的問題解決&#xff0c;后端項目可以啟動&#xff0c;前端頁面也集成進去。 前端在流程設計頁面報錯 之后發現主要是組件中modelerStore這個值沒有 解決方法:在data增加對象 給component/process/designer.vue 中涉及到的每個子組件傳入 :modelerStore“modeler…

Prometheus Exporter系列-Mysql_Exporter一鍵部署

新項目舊項目都需要給研發配置mysql監控&#xff0c;這里mysql監控對應aws 阿里云 騰訊云 華為云的云mysql產品或開源自建mysql。 exporter安裝雖然簡單&#xff0c;經常手動操作不免讓人心煩&#xff0c;一鍵完成省去繁瑣的常規操作。 配置信息對的情況下測試多次都可以正常安…

2025年移動端開發性能優化實踐與趨勢分析

啟動速度優化 本質&#xff1a;縮短首次可見幀渲染時間。 方法&#xff1a; iOS&#xff1a;利用Core ML本地模型輕量化部署&#xff0c;減少云端等待。Android&#xff1a;強制啟用SplashScreen API&#xff0c;通過setKeepOnScreenCondition控制動畫時長。冷啟動需將耗時操…

【MySQL篇】DEPENDENT SUBQUERY(依賴性子查詢)優化:從百秒到秒級響應的四種優化辦法

&#x1f4ab;《博主介紹》&#xff1a;?又是一天沒白過&#xff0c;我是奈斯&#xff0c;從事IT領域? &#x1f4ab;《擅長領域》&#xff1a;??擅長阿里云AnalyticDB for MySQL(分布式數據倉庫)、Oracle、MySQL、Linux、prometheus監控&#xff1b;并對SQLserver、NoSQL(…

全文 - MLIR Toy Tutorial Chapter 1: Toy Language and AST

Toy 語言 本教程&#xff0c;將會借助一個玩具語言來講解&#xff0c;這個語言我們稱其為 Toy。Toy 是一個基于張量的語言&#xff0c;它允許你定義函數&#xff0c;執行一些數學計算&#xff0c;并且打印結果。做這樣的設定&#xff0c;是因為我們希望讓教程保持簡明&#xff…

排序復習_代碼純享

頭文件 #pragma once #include<iostream> #include<vector> #include<utility> using std::vector; using std::cout; using std::cin; using std::endl; using std::swap;//插入排序 //1、直接插入排序&#xff08;穩定&#xff09; void InsertSort(vecto…

CSS語言的雙向鏈表

CSS語言的雙向鏈表 引言 在計算機科學中&#xff0c;數據結構是一個極為重要的概念&#xff0c;而鏈表則是最常見的數據結構之一。鏈表可以分為單向鏈表和雙向鏈表&#xff0c;其中雙向鏈表因其靈活性和高效性而受到廣泛應用。在前端開發的領域&#xff0c;尤其是CSS&#xf…

簡單理解機器學習中top_k、top_p、temperature三個參數的作用

AI系列文章&#xff1a; AWS AI認證考試中經常提及幾個重要的工具介紹 簡單理解機器學習中top_k、top_p、temperature三個參數的作用 用Deepseek Kimi 快速生成高質量的ppt 在機器學習中&#xff0c;top_k、top_p 和 temperature 是用于控制生成模型&#xff08;如語言模型…

紅寶書第十三講:詳解JavaScript核心對象:Array、Object、Date、RegExp

紅寶書第十三講&#xff1a;詳解JavaScript核心對象&#xff1a;Array、Object、Date、RegExp 資料取自《JavaScript高級程序設計&#xff08;第5版&#xff09;》。 查看總目錄&#xff1a;紅寶書學習大綱 一、Object&#xff1a;萬物皆對象的“盒子” Object是JavaScript中…

昆侖技術重構AI大模型落地范式,長期作“加法”迎來國產生態化“拐點”

作者 | 曾響鈴 文 | 響鈴說 DeepSeek的爆火&#xff0c;在業內迅速掀起了一場國產化的變革。“國產大模型國產算力”軟硬協同的范式正在被重構&#xff0c;AI產業國產化的含金量持續提升&#xff0c;越來越多的企業在這一趨勢下加速走上數智化轉型路徑。 其中&#xff0c;以…

原開源鴻蒙倉庫停止更新

2月24日&#xff0c;gitee 上的開源鴻蒙組織&#xff0c;所有代碼停止更新&#xff0c;查看代碼倉顯示已關閉&#xff0c;不少小伙伴以為停止更新了&#xff0c;發生了什么&#xff1f; 原因很簡單&#xff0c;所有代碼倉遷移至 Gitcode&#xff0c;至于為什么改用 Gitcode&…

Spring Boot框架中常用注解

以下是Spring Boot框架中常用注解的詳細說明&#xff0c;包括名稱、用途、用法、使用位置及擴展示例&#xff0c;按功能模塊分類整理&#xff1a; 一、核心啟動與配置注解 1. SpringBootApplication 用途&#xff1a;主啟動類注解&#xff0c;整合了 Configuration、EnableAu…

Azure Delta Lake、Databricks和Event Hubs實現實時欺詐檢測

設計Azure云架構方案實現Azure Delta Lake和Azure Databricks&#xff0c;結合 Azure Event Hubs/Kafka 攝入實時數據&#xff0c;通過 Delta Lake 實現 Exactly-Once 語義&#xff0c;實時欺詐檢測&#xff08;流數據寫入 Delta Lake&#xff0c;批處理模型實時更新&#xff0…

車載以太網網絡測試 -23【TCPUDP通信示例】

1 摘要 在車載通信場景中&#xff0c;TCP以及UDP的通信可以用于多種應用&#xff0c;例如車輛狀態監控、遠程控制、數據采集等。以下是詳細的代碼示例&#xff0c;展示了如何使用Python實現簡單的TCP客戶端與服務端通信以及簡單的UDP客戶端與服務端通信&#xff0c;并模擬了車…

SpringBoot大學生競賽管理系統設計與實現

一個用于管理大學生競賽報名、信息查詢與競賽管理的系統&#xff0c;采用了現代化的SpringBoot框架進行開發。該系統的主要功能包括學生信息管理、教師信息管理、競賽報名審核、競賽信息管理等模塊&#xff0c;適用于學校或教育機構進行競賽活動的組織與管理。系統界面簡潔&…