Skip to content

Commit

Permalink
add data binding and format rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
memory125 committed Jan 26, 2022
1 parent 82f5b26 commit 6ad2817
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 1 deletion.
40 changes: 40 additions & 0 deletions web/gin/10-jsonbinding.go
@@ -0,0 +1,40 @@
package main

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

// gin - 数据解析和绑定: Json

// 定义接收数据的结构体
type LoginJson struct {
// binding:"required"修饰的字段,若接收为空值,则报错,是必须字段
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() {
// 1.创建路由
// 默认使用了2个中间件Logger(), Recovery()
r := gin.Default()
// JSON绑定
r.POST("loginJSON", func(c *gin.Context) {
// 声明接收的变量
var json LoginJson
// 将request的body中的数据,自动按照json格式解析到结构体
if err := c.ShouldBindJSON(&json); err != nil {
// 返回错误信息
// gin.H封装了生成json数据的工具
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 判断用户名密码是否正确
if json.User != "root" || json.Password != "admin" {
c.JSON(http.StatusBadRequest, gin.H{"status": "304"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "200"})
})
r.Run(":8000")
}
39 changes: 39 additions & 0 deletions web/gin/11-formbinding.go
@@ -0,0 +1,39 @@
package main

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

// gin - 数据解析和绑定: Form

// 定义接收数据的结构体
type LoginForm struct {
// binding:"required"修饰的字段,若接收为空值,则报错,是必须字段
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() {
// 1.创建路由
// 默认使用了2个中间件Logger(), Recovery()
r := gin.Default()
// JSON绑定
r.POST("/loginForm", func(c *gin.Context) {
// 声明接收的变量
var form LoginForm
// Bind()默认解析并绑定form格式
// 根据请求头中content-type自动推断
if 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{"status": "304"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "200"})
})
r.Run(":8000")
}
39 changes: 39 additions & 0 deletions web/gin/12-uribinding.go
@@ -0,0 +1,39 @@
package main

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

// gin - 数据解析和绑定: URI

// 定义接收数据的结构体
type LoginURI struct {
// binding:"required"修饰的字段,若接收为空值,则报错,是必须字段
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() {
// 1.创建路由
// 默认使用了2个中间件Logger(), Recovery()
r := gin.Default()
// JSON绑定
r.GET("/:user/:password", func(c *gin.Context) {
// 声明接收的变量
var login LoginURI
// Bind()默认解析并绑定form格式
// 根据请求头中content-type自动推断
if err := c.ShouldBindUri(&login); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 判断用户名密码是否正确
if login.User != "root" || login.Password != "admin" {
c.JSON(http.StatusBadRequest, gin.H{"status": "304"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "200"})
})
r.Run(":8000")
}
54 changes: 54 additions & 0 deletions web/gin/13-dataformatrender.go
@@ -0,0 +1,54 @@
package main

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

// gin - 各种数据格式的响应

// 多种响应方式
func main() {
// 1.创建路由
// 默认使用了2个中间件Logger(), Recovery()
router := gin.Default()
// 1.json
router.GET("/json", func(c *gin.Context) {
c.JSON(200, gin.H{"msg": "json rendering", "status": 200})
})
// 2. 结构体响应
router.GET("/struct", func(c *gin.Context) {
var msg struct {
Name string
Message string
Number int
}
msg.Name = "struct"
msg.Message = "message"
msg.Number = 123
c.JSON(200, msg)
})
// 3.XML
router.GET("/xml", func(c *gin.Context) {
c.XML(200, gin.H{"msg": "xml rendering"})
})
// 4.YAML响应
router.GET("/yaml", func(c *gin.Context) {
c.YAML(200, gin.H{"msg": "yaml rendering"})
})
// 5.protobuf格式,谷歌开发的高效存储读取的工具
// 数组?切片?如果自己构建一个传输格式,应该是什么格式?
router.GET("/protobuf", func(c *gin.Context) {
reps := []int64{int64(1), int64(2)}
// 定义数据
label := "protobuf"
// 传protobuf格式数据
data := &protoexample.Test{
Label: &label,
Reps: reps,
}
c.ProtoBuf(200, data)
})

router.Run(":8000")
}
19 changes: 18 additions & 1 deletion web/gin/gin.md
Expand Up @@ -43,5 +43,22 @@
- `multipart/form-data`格式用于文件上传
- gin文件上传与原生的`net/http`方法类似,不同在于gin把原生的request封装到`c.Request`

## routes group
## routers group(路由组)
- routes group是为了管理一些相同的URL

## gin数据解析和绑定
- Json 数据解析和绑定
- 客户端传参,后端接收并解析到结构体
- 表单数据解析和绑定
- URI数据解析和绑定

## gin渲染
- 各种数据格式的响应
- Json、结构体、XML、YAML类似于java的properties、ProtoBuf
- HTML模板渲染
- gin支持加载HTML模板, 然后根据模板参数进行配置并返回相应的数据,本质上就是字符串替换
- `LoadHTMLGlob()`方法可以加载模板文件
- 重定向 - `gin.context.redirect()`
- 同步异步
- `goroutine`机制可以方便地实现异步处理
- 在启动新的`goroutine`时,不应该使用原始上下文,必须使用它的只读副本
17 changes: 17 additions & 0 deletions web/gin/html/11-formbinding.html
@@ -0,0 +1,17 @@
<!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表单-->
<form action="http://localhost:8000/loginForm" method="post" enctype="application/x-www-form-urlencoded">
用户名<input type="text" name="username"><br>
密码<input type="password" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>

0 comments on commit 6ad2817

Please sign in to comment.