Skip to content

老陈是一个普通的文艺二逼青年

For The Dream

gin框架入门

Written by chen

安装

1
2
go get -u -v github.com/gin-gonic/gin
 

快速入门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main
 
import (
    "github.com/gin-gonic/gin"
)
 
func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // listen and serve on 0.0.0.0:8080
}
 
# 访问 http://192.168.31.105:8080/ping
# 返回
# {
#     message: "pong"
# }
 

实现无缝重启、停机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 使用 fvbock/endless, 不兼容windows
 
package main
 
import (
    "github.com/fvbock/endless"
    "github.com/gin-gonic/gin"
)
 
func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    endless.ListenAndServe("0.0.0.0:8080", r)
}
 
 

GET, POST, PUT, PATCH, DELETE and OPTIONS

1
2
3
4
5
6
7
8
    router.GET("/someGet", getting)
    router.POST("/somePost", posting)
    router.PUT("/somePut", putting)
    router.DELETE("/someDelete", deleting)
    router.PATCH("/somePatch", patching)
    router.HEAD("/someHead", head)
    router.OPTIONS("/someOptions", options)
 

带参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main
 
import (
    "github.com/gin-gonic/gin"
    "net/http"
)
 
func main() {
    router := gin.Default()
 
    router.GET("/user/:name", func(c *gin.Context) {
        name := c.Param("name")
        c.String(http.StatusOK, "Hello %s", name)
    })
 
    router.GET("/user/:name/*action", func(c *gin.Context) {
        name := c.Param("name")
        action := c.Param("action")
        message := name + " is " + action
        c.String(http.StatusOK, message)
    })
 
    router.Run(":8080")
}
 

query 参数

1
2
3
4
5
6
7
8
9
10
11
    router.GET("/user/:name/*action", func(c *gin.Context) {
        name := c.Param("name")
        action := c.Param("action")
 
        lastname := c.DefaultQuery("lastname", "Guest") //可设置默认值
        // lastname := c.Query("lastname") // 是 c.Request.URL.Query().Get("lastname") 的简写
 
        message := name + " - " + lastname + " is " + action
        c.String(http.StatusOK, message)
    })
 

post请求

1
2
3
4
5
6
7
8
9
10
11
12
router.POST("/form_post", func(c *gin.Context) {
        message := c.PostForm("message")
        nick := c.DefaultPostForm("nick", "anonymous")
 
        c.JSON(200, gin.H{
            "status":  "posted",
            "message": message,
            "nick":    nick,
        })
    })
 
 

上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
router.POST("/upload", func(c *gin.Context) {
        // single file
        file, _ := c.FormFile("file")
        log.Println(file.Filename)
 
        // Upload the file to specific dst.
        c.SaveUploadedFile(file, file.Filename) // 保存
        // file.Filename 是保存路径。保存在当前目录下的该文件名
        // 也可以使用绝对路径
 
        c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
    })
 
 

分组路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    // Simple group: v1
    v1 := router.Group("/v1")
    {
        v1.POST("/login", func(c *gin.Context) {
 
            c.String(http.StatusOK, "v1.login")
        })
        v1.POST("/submit", func(c *gin.Context) {
 
            c.String(http.StatusOK, "v1.submit")
        })
        v1.POST("/read", func(c *gin.Context) {
 
            c.String(http.StatusOK, "v1.read")
        })
    }
 
    // Simple group: v2
    v2 := router.Group("/v2")
    {
        v2.POST("/login", func(c *gin.Context) {
 
            c.String(http.StatusOK, "v2.login")
        })
        v2.POST("/submit", func(c *gin.Context) {
 
            c.String(http.StatusOK, "v2.submit")
        })
        v2.POST("/read", func(c *gin.Context) {
 
            c.String(http.StatusOK, "v2.read")
        })
    }
 

  • 访问 192.168.31.105:8080/v1/submit 返回 v1.submit
  • 访问 192.168.31.105:8080/v2/submit 返回 v2.submit
使用中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package main
 
import (
    "fmt"
    "github.com/gin-gonic/gin"
    "log"
    "net/http"
)
 
func main() {
    r := gin.New()
 
    // 全局中间件
    r.Use(gin.Logger())
    r.Use(gin.Recovery())
    r.Use(func(c *gin.Context) {
        log.Println("mid before")
        c.Next()
        log.Println("mid after")
    })
 
    r.GET("/echo", func(c *gin.Context) {
        fmt.Println("echo 1")
    }, func(c *gin.Context) {
        fmt.Println("echo 2")
    })
 
    // 组中间件
    v1 := r.Group("/v1")
    v1.Use(func(c *gin.Context) {
        log.Println("group mid before")
        c.Next()
        log.Println("group mid after")
    })
    {
        v1.POST("/login", func(c *gin.Context) {
 
            c.String(http.StatusOK, "v1.login")
        })
        v1.POST("/submit", func(c *gin.Context) {
 
            c.String(http.StatusOK, "v1.submit")
        })
        v1.POST("/read", func(c *gin.Context) {
 
            c.String(http.StatusOK, "v1.read")
        })
    }
 
    r.Run(":8080")
}
 

请求日志记录文件

1
2
3
4
5
6
    # 初始化gin框架前,先进行设置
    gin.DisableConsoleColor()
    f, _ := os.Create("gin.log")
    gin.DefaultWriter = io.MultiWriter(f)
 
 

绑定参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    // 绑定json
    // Example for binding JSON ({"user": "manu", "password": "123"})
    router.POST("/loginJSON", func(c *gin.Context) {
        var json Login
        if err := c.ShouldBindJSON(&json); err == nil {
            fmt.Println(json)
            if json.User == "manu" && json.Password == "123" {
                c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
            } else {
                c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
            }
        } else {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        }
    })
 
    // 绑定form表单
    // Example for binding a HTML form (user=manu&password=123)
    router.POST("/loginForm", func(c *gin.Context) {
        var form Login
        // This will infer what binder to use depending on the content-type header.
        if err := c.ShouldBind(&form); err == nil {
            fmt.Println(form)
            if form.User == "manu" && form.Password == "123" {
                c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
            } else {
                c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
            }
        } else {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        }
    })
 

跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# http 重定向
r.GET("/test", func(c *gin.Context) {
    c.Redirect(http.StatusMovedPermanently, "http://www.google.com/")
})
 
# 路由重定向
r.GET("/test", func(c *gin.Context) {
    c.Request.URL.Path = "/test2"
    r.HandleContext(c)
})
r.GET("/test2", func(c *gin.Context) {
    c.JSON(200, gin.H{"hello": "world"})
})
 

gin · golang

Copyright © 2022 老陈是一个普通的文艺二逼青年. 沪ICP备13044041号-1