文章首发于:clawhub.club


框架的使用对于敏捷开发来说是非常重要的,虽然有不要重复造轮子的老话,但是在使用框架的同时一定要学习人家的思想与实现方式,免得发生没了框架就不会写代码的境地。
Gin的github地址:
https://github.com/gin-gonic/gin
中文文档地址:
https://gin-gonic.com/zh-cn/docs/

学习例子

1 hello word

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import (
"gopkg.in/gin-gonic/gin.v1"
"net/http"
)

func main(){

router := gin.Default()

router.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "Hello World")
})
router.Run(":8000")
}

2 GET请求

1
2
3
4
5
6
7
8
func main(){
router := gin.Default()

router.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
})
}

3简单的post请求

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

c.JSON(http.StatusOK, gin.H{
"status": gin.H{
"status_code": http.StatusOK,
"status": "ok",
},
"message": message,
"nick": nick,
})
})

4 PUT 请求

1
2
3
4
5
6
7
8
9
10
router.PUT("/post", func(c *gin.Context) {
id := c.Query("id")
page := c.DefaultQuery("page", "0")
name := c.PostForm("name")
message := c.PostForm("message")
fmt.Printf("id: %s; page: %s; name: %s; message: %s \n", id, page, name, message)
c.JSON(http.StatusOK, gin.H{
"status_code": http.StatusOK,
})
})

5上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
router.POST("/upload", func(c *gin.Context) {
name := c.PostForm("name")
fmt.Println(name)
file, header, err := c.Request.FormFile("upload")
if err != nil {
c.String(http.StatusBadRequest, "Bad request")
return
}
filename := header.Filename

fmt.Println(file, err, filename)

c.String(http.StatusCreated, "upload successful")
})

6 批量上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
router.POST("/multi/upload", func(c *gin.Context) {
err := c.Request.ParseMultipartForm(200000)
if err != nil {
log.Fatal(err)
}

formdata := c.Request.MultipartForm
files := formdata.File["upload"]
for i := range files {
file, err := files[i].Open()
filename := files[i].Filename
fmt.Println(file, err, filename)
defer file.Close()
if err != nil {
log.Fatal(err)
}
c.String(http.StatusCreated, "upload successful")

}

})

####7 c.HTML模板

1
2
3
4
router.LoadHTMLGlob("G:\\GO\\src\\go-study\\src\\templates/*")
router.GET("/upload", func(c *gin.Context) {
c.HTML(http.StatusOK, "upload.html", gin.H{})
})

####8 c.BindJSON和c.BindWith

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
router.POST("/login", func(c *gin.Context) {
var user User
var err error
contentType := c.Request.Header.Get("Content-Type")

switch contentType {
case "application/json":
err = c.BindJSON(&user)
case "application/x-www-form-urlencoded":
err = c.BindWith(&user, binding.Form)
}

if err != nil {
fmt.Println(err)
log.Fatal(err)
}

c.JSON(http.StatusOK, gin.H{
"user": user.Username,
"passwd": user.Passwd,
"age": user.Age,
})

})

9 自动Bind

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
router.POST("/login", func(c *gin.Context) {
var user User

err := c.Bind(&user)
if err != nil {
fmt.Println(err)
log.Fatal(err)
}

c.JSON(http.StatusOK, gin.H{
"username": user.Username,
"passwd": user.Passwd,
"age": user.Age,
})

})

10 c.JSON与c.XML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
router.GET("/render", func(c *gin.Context) {
contentType := c.DefaultQuery("content_type", "json")
if contentType == "json" {
c.JSON(http.StatusOK, gin.H{
"user": "rsj217",
"passwd": "123",
})
} else if contentType == "xml" {
c.XML(http.StatusOK, gin.H{
"user": "rsj217",
"passwd": "123",
})
}

})

11 重定向

1
2
3
4
//重定向
router.GET("/redict/google", func(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, "https://google.com")
})

12 路由分组

1
2
3
4
5
6
7
8
9
10
11
12
//分组路由
v1 := router.Group("/v1")

v1.GET("/login", func(c *gin.Context) {
c.String(http.StatusOK, "v1 login")
})

v2 := router.Group("/v2")

v2.GET("/login", func(c *gin.Context) {
c.String(http.StatusOK, "v2 login")
})

13 middleware中间件

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
53
54
55
56
57
58
59
60
61
62
	//全局中间件
router.Use(MiddleWare())
{
router.GET("/middleware", func(c *gin.Context) {
request := c.MustGet("request").(string)
req, _ := c.Get("request")
c.JSON(http.StatusOK, gin.H{
"middile_request": request,
"request": req,
})
})
}
//单个路由中间件
router.GET("/before", MiddleWare(), func(c *gin.Context) {
request := c.MustGet("request").(string)
c.JSON(http.StatusOK, gin.H{
"middile_request": request,
})
})
//鉴权中间件
router.GET("/auth/signin", func(c *gin.Context) {
cookie := &http.Cookie{
Name: "session_id",
Value: "123",
Path: "/",
HttpOnly: true,
}
http.SetCookie(c.Writer, cookie)
c.String(http.StatusOK, "Login successful")
})

router.GET("/home", AuthMiddleWare(), func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"data": "home"})
})
//鉴权中间件
func AuthMiddleWare() gin.HandlerFunc {
return func(c *gin.Context) {
if cookie, err := c.Request.Cookie("session_id"); err == nil {
value := cookie.Value
fmt.Println(value)
if value == "123" {
c.Next()
return
}
}
c.JSON(http.StatusUnauthorized, gin.H{
"error": "Unauthorized",
})
c.Abort()
return
}
}

//全局中间件
func MiddleWare() gin.HandlerFunc {
return func(c *gin.Context) {
fmt.Println("before middleware")
c.Set("request", "clinet_request")
c.Next()
fmt.Println("before middleware")
}
}

14 异步协程

1
2
3
4
5
//异步协程
router.GET("/sync", func(c *gin.Context) {
time.Sleep(5 * time.Second)
log.Println("Done! in path" + c.Request.URL.Path)
})

15 自定义router

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	//自定义router
router.GET("/async", func(c *gin.Context) {
cCp := c.Copy()
go func() {
time.Sleep(5 * time.Second)
log.Println("Done! in path" + cCp.Request.URL.Path)
}()
})
s := &http.Server{
Addr: ":8000",
Handler: router,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
s.ListenAndServe()
//_ = router.Run(":8000")
}