gin框架学习笔记

gin的第一个程序

package main

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

func main() {
   // 创建一个默认的路由引擎
   r := gin.Default()
   // GET:请求方式;/hello:请求的路径
   // 当客户端以GET方法请求/hello路径时,会执行后面的匿名函数
   r.GET("/hello", func(c *gin.Context) {
      // c.JSON:返回JSON格式的数据
      c.JSON(200, gin.H{
         "message": "Hello world!",
      })
   })
   // 启动HTTP服务,默认在0.0.0.0:8080启动服务
   r.Run()
}

gin框架返回JSON

package main

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

func main() {
   r := gin.Default()
   
   r.GET("/json", func(c *gin.Context) {
   // 方法1:使用map
      data := map[string]interface{}{
         "name": "小王子",
         "message":"hello world!",
         "age":18,
      }
   // 等价于
   data := gin.H{"name": "小王子","message":"hello world!", "age":18,}
      c.JSON(http.StatusOK,data)
   })
   r.Run(":9090")
}
package main

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

func main() {
   r := gin.Default()

   //方法2 结构体
   type  msg struct  {
      Name string
      Message string
      Age int
   }
   r.GET("/json", func(c *gin.Context) {
      data := msg{
         "小王子",
         "Hello golang!",
         18,
      }

      c.JSON(http.StatusOK,data)
   })
   r.Run(":9090")
}

gin获取querystring参数

package main

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

func main() {
   r := gin.Default()
   // GET请求 URL ? 后面的事querystring参数
   // key=value格式,多个key-value用 & 连接
   r.GET("/web", func(c *gin.Context) {
   // 获取浏览器那边发请求携带的query string 参数
      name := c.Query("query")  //通过Query获取请求中携带的querystring参数
      name1 := c.DefaultQuery("query","somebody") //取不到就用指定的默认值
      name2,ok := c.GetQuery("query")    //取不到第二个参数就返回false
      if !ok{
      // 取不到值
         name2="sb"
      }
      c.JSON(http.StatusOK,gin.H{
         "name" : name,
         "name1": name1,
         "name2": name2,
      })

   })
   r.Run(":9090")
}

gin获取form参数

登陆表单实例

main.go

package main

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

func main() {
   r := gin.Default()
   r.LoadHTMLFiles("./login.html","./index.html")
   r.GET("/login", func(c *gin.Context) {
      c.HTML(http.StatusOK,"login.html",nil)
   })
   // login post
   r.POST("/login", func(c *gin.Context) {
      //获取form表单提交的数据  1
      username:=c.PostForm("username")
      password:=c.PostForm("password")
      // 2
      username1:=c.DefaultPostForm("username","somebody")
      password1:=c.DefaultPostForm("password","***")
      //3
      username2,ok :=c.GetPostForm("username")
      if !ok {
         username2="sb"
      }
      password2,ok :=c.GetPostForm("password")
      if !ok {
      password2="***"
      }
      c.HTML(http.StatusOK,"index.html",gin.H{
         "Name":username,
         "password":password,
         "Name1":username1,
         "password1":password1,
         "Name2":username2,
         "password2":password2,
      })
   })
   r.Run(":9090")
}

login.html




    
    login



index.html




    
    index


Hello ,{{.Name}} !

你的密码是:{{.password}}

Hello ,{{.Name1}} !

你的密码是:{{.password1}}

Hello ,{{.Name2}} !

你的密码是:{{.password2}}

gin获取URL路径参数

package main

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

func main() {
   r := gin.Default()
   r.GET("/user/:name/:age", func(c *gin.Context) {
      //获取路径参数
      name := c.Param("name")
      age := c.Param("age")
      c.JSON(http.StatusOK,gin.H{
         "name" :name,
         "age":age,
      })
   })

   r.GET("/blog/:year/:month", func(c *gin.Context) {
      //获取路径参数
      year := c.Param("year")
      month := c.Param("month")
      c.JSON(http.StatusOK,gin.H{
         "year" :year,
         "month":month,
      })
   })

   r.Run(":9090")
}

gin参数绑定

package main

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

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

func main() {
   r := gin.Default()
   r.GET("/user", func(c *gin.Context) {
      //username := c.Query("username")
      //password := c.Query("password")
      //u := UserInfo{
      // username: username,
      // password:password,
      //}
      var u UserInfo  //声明一个UserInfo类型的变量
      err :=c.ShouldBind(&u)
      if err!=nil {
         c.JSON(http.StatusBadRequest,gin.H{
            "error": err.Error(),
         })
      }else {
         fmt.Printf("%#v\n",u)
         c.JSON(http.StatusOK,gin.H{
            "status":"ok",
         })
      }

   })

   r.POST("/form", func(c *gin.Context) {
      var u UserInfo  //声明一个UserInfo类型的变量
      err :=c.ShouldBind(&u)
      if err!=nil {
         c.JSON(http.StatusBadRequest,gin.H{
            "error": err.Error(),
         })
      }else {
         fmt.Printf("%#v\n",u)
         c.JSON(http.StatusOK,gin.H{
            "status":"ok",
         })
      }

   })

   r.Run(":9090")
}

gin文件上传

上传案例

main.go

package main

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


func main() {
   r := gin.Default()
   r.LoadHTMLFiles("./index.html")
   r.GET("/index", func(c *gin.Context) {
      c.HTML(http.StatusOK, "index.html", nil)
   })
   
   r.POST("/upload", func(c *gin.Context) {
      //从请求中读取文件
      f,err := c.FormFile("f1") //从请求中获取携带的参数一样的
      if err != nil {
         c.JSON(http.StatusOK,gin.H{
            "error":err.Error(),
         })
      }else {
         //将读取到的文件保存在本地(服务器本地)
         //dst := fmt.Sprintf("./%s",f.Filename)
         dst := path.Join("./",f.Filename)
         c.SaveUploadedFile(f,dst)
         c.JSON(http.StatusOK,gin.H{
            "status":"ok",
         })
      }

   })
      r.Run(":9090")
}

index.html




    
    index



gin请求重定向

package main

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


func main() {
   r := gin.Default()
   r.GET("/index", func(c *gin.Context) {
      //c.JSON(http.StatusOK,gin.H{
      // "status":"ok",
      //})
      //跳转到搜狗网站
      c.Redirect(http.StatusMovedPermanently,"http://www.sogo.com")
   })

   r.GET("/a", func(c *gin.Context) {
      //跳转到  /b  对应的路由处理函数
      c.Request.URL.Path ="/b"   //把请求的URI修改
      r.HandleContext(c)  //继续后续的处理
   })

   r.GET("/b", func(c *gin.Context) {
      c.JSON(http.StatusOK,gin.H{
         "message":"b",
      })
   })
      r.Run(":9090")
}

gin路由和路由组

package main

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


func main() {
   r := gin.Default()
   // 访问/index的GET请求会走这一条处理逻辑
   // 路由
   r.GET("/index", func(c *gin.Context) {
      c.JSON(http.StatusOK,gin.H{
         "method":"GET",
      })
   })
   r.POST("/index", func(c *gin.Context) {
      c.JSON(http.StatusOK,gin.H{
         "method":"POST",
      })
   })

   r.PUT("/index", func(c *gin.Context) {
      c.JSON(http.StatusOK,gin.H{
         "method":"PUT",
      })
   })

   r.DELETE("/index", func(c *gin.Context) {
      c.JSON(http.StatusOK,gin.H{
         "method":"DELETE",
      })
   })

   //Any 请求方法大集合
   r.Any("/user", func(c *gin.Context) {
      switch c.Request.Method {
      case http.MethodGet:
         c.JSON(http.StatusOK,gin.H{"method":"GET"})
      case http.MethodPost:
         c.JSON(http.StatusOK,gin.H{"method":"POST"})
      case http.MethodDelete:
         c.JSON(http.StatusOK,gin.H{"method":"DELETE"})
      }
   // 等等
   })

   //NoRoute  访问没有设置的路由的时候 访问这个
   r.NoRoute(func(c *gin.Context) {
      c.JSON(http.StatusNotFound,gin.H{"msg":"liwenzhou.com"})
   })

   //路由组
   //把共用的前缀提取出来,创建一个路由组
   videoGroup := r.Group("/video")
   {
      videoGroup.GET("/index", func(c *gin.Context) {
         c.JSON(http.StatusOK,gin.H{"msg":"/video/index"})
      })
      videoGroup.GET("/oo", func(c *gin.Context) {
         c.JSON(http.StatusOK,gin.H{"msg":"/video/oo"})
      })
      videoGroup.GET("/xx", func(c *gin.Context) {
         c.JSON(http.StatusOK,gin.H{"msg":"/video/xx"})
      })
   }

      r.Run(":9090")
}

gin中间件

package main

import (
   "fmt"
   "github.com/gin-gonic/gin"
   "net/http"
   "time"
)
//handlerFunc 类型
func indexHandler(c *gin.Context) {
   fmt.Println("index")
   c.JSON(http.StatusOK,gin.H{
      "msg":"index",
   })
}

//定义一个中间件 m1
func m1(c *gin.Context)  {
   fmt.Println("m1 in ...")
   //计时
   start := time.Now()
   c.Next() //调用后续的处理函数
   //c.Abort() //阻止调用后续的处理函数
   cost := time.Since(start)
   fmt.Printf("cost:%v\n",cost)
   fmt.Println("mi out ...  ")
}

//定义一个中间件 m2
func m2(c *gin.Context)  {
   fmt.Println("m2 in ...")
   c.Next()
   fmt.Println("m2 out ...  ")
}

func main(){
   r := gin.Default()
   r.Use(m1,m2) //全局注册中间件
   r.GET("/index", indexHandler)
   r.GET("/user", func(c *gin.Context) {
      c.JSON(http.StatusOK,gin.H{
         "msg":"user",
      })
   })
   r.GET("/shop", func(c *gin.Context) {
      c.JSON(http.StatusOK,gin.H{
         "msg":"user",
      })
   })


      r.Run(":9090")
}
package main

import (
   "fmt"
   "github.com/gin-gonic/gin"
   "net/http"
   "time"
)
//handlerFunc 类型
func indexHandler(c *gin.Context) {
   fmt.Println("index")
   name,ok := c.Get("name") //从上下文c中取值
   if !ok {
      name="匿名用户"
   }
   c.JSON(http.StatusOK,gin.H{
      "msg":name,
   })
}

//定义一个中间件 m1
func m1(c *gin.Context)  {
   fmt.Println("m1 in ...")
   //计时
   start := time.Now()
   c.Next() //调用后续的处理函数
   //c.Abort() //阻止调用后续的处理函数
   cost := time.Since(start)
   fmt.Printf("cost:%v\n",cost)
   fmt.Println("mi out ...  ")
}

//定义一个中间件 m2
func m2(c *gin.Context)  {
   fmt.Println("m2 in ...")
   c.Set("name","吴天骄") //在上下文c 中设置值
   //c.Next()
   //c.Abort() //阻止调用后续的处理函数
   //return  //直接结束m2
   fmt.Println("m2 out ...  ")
}

func authMiddleware(deCheck bool) gin.HandlerFunc  {
   //连接数据库
   //或者一些其他准备工作
   return func(c *gin.Context) {
      if deCheck {
         //存放具体的逻辑
         //是否登录的判断
         //if 是登陆用户
         // c.Next()
         //else
         //c.About()
      }else {
         c.Next()
      }
   }
}

func main(){
   r := gin.Default()
   r.Use(m1,m2,authMiddleware(true)) //全局注册中间件
   r.GET("/index", indexHandler)
   r.GET("/user", func(c *gin.Context) {
      c.JSON(http.StatusOK,gin.H{
         "msg":"user",
      })
   })
   r.GET("/shop", func(c *gin.Context) {
      c.JSON(http.StatusOK,gin.H{
         "msg":"user",
      })
   })

   //路由注册中间件 方法1:
   xx1Group := r.Group("/xx1", authMiddleware(true))
   {
      xx1Group.GET("/index", func(c *gin.Context) {
         c.JSON(http.StatusOK,gin.H{
            "msg":"xx1Group",
         })
      })
   }
   //路由注册中间件 方法2:
   xx2Group := r.Group("/xx2")
   xx2Group.Use(authMiddleware(true))
   {
      xx2Group.GET("/index", func(c *gin.Context) {
         c.JSON(http.StatusOK,gin.H{
            "msg":"xx2Group",
         })
      })
   }

      r.Run(":9090")
}

中间件注意事项

gin默认中间件

gin.Default()默认使用了Logger和Recovery中间件,其中:

  • Logger中间件将日志写入gin.DefaultWriter,即使配置了GIN_MODE=release。
  • Recovery中间件会recover任何panic。如果有panic的话,会写入500响应码。

如果不想使用上面两个默认的中间件,可以使用gin.New()新建一个没有任何默认中间件的路由。

gin中间件中使用goroutine

当在中间件或handler中启动新的goroutine时,不能使用原始的上下文(c *gin.Context),必须使用其只读副本(c.Copy())。

你可能感兴趣的:(go,golang,go,后端,中间件)