1.接收请求参数
c.Param()
c.Query
c.DefaultQuery
c.PostForm
c.DefaultPostForm
c.QueryMap
c.PostFormMap
c.FormFile
c.MultipartForm
1.1 GET请求参数(c.Query)
func main() {
r := gin.Default()
r.GET("/user", func(c *gin.Context) {
// 使用query获取请求参数
username := c.Query("username")
password := c.Query("password")
fmt.Println(username) // linjing
fmt.Println(password) // 123
// 返回请求参数 JSON
c.JSON(200, gin.H{
"username": username,
"password": password,
})
})
// 运行服务
r.Run(":8080")
}
postman 测试: 127.0.0.1:8080/user?username=linjing&password=123
1.2 POST请求参数-Form表单(c.PostForm)
func main() {
r := gin.Default()
// 使用POST请求并获取参数
r.POST("/user", func(c *gin.Context) {
// 使用PostForm获取请求参数
username := c.PostForm("username")
password := c.PostForm("password")
// 返回请求参数 JSON
c.JSON(200, gin.H{
"username": username,
"password": password,
})
})
// 运行服务
r.Run(":8080")
}
1.3 POST请求参数-JSON格式(c.BindJSON)
func main() {
r := gin.Default()
// 使用POST请求并获取参数
r.POST("/user", func(c *gin.Context) {
var user User
if err := c.BindJSON(&user); err != nil {
// 返回错误信息
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
// 返回请求参数
c.JSON(200, gin.H{
"username": user.Username,
"password": user.Password,
})
})
r.Run(":8080")
}
type User struct {
Username string `json:"username"`
Password string `json:"password"`
}
1.4 URL参数
func main() {
r := gin.Default()
// 使用url传参 并获取参数
r.GET("/user/:username/:password", func(c *gin.Context) {
// 使用param获取URL参数
username := c.Param("username")
password := c.Param("password")
// 返回请求参数
c.JSON(200, gin.H{
"username": username,
"password": password,
})
})
// 运行服务
r.Run(":8080")
}
1.5 请求头部参数
func main() {
r := gin.Default()
// 使用请求头参数
r.GET("/user", func(c *gin.Context) {
// 使用request获取请求头参数
username := c.Request.Header.Get("username")
password := c.Request.Header.Get("password")
// 返回请求参数
c.JSON(200, gin.H{
"username": username,
"password": password,
})
})
// 运行服务
r.Run(":8080")
}
2. 响应请求参数
1.BindJSON()
通过BindJSON()将json请求体绑定到一个结构体上。
type User struct {
Username string `json:"username"`
Password string `json:"password"`
}
// main()中代码
var user User
if err := c.BindJSON(&user); err != nil {
// 返回错误信息
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
fmt.Println(user.Username)
fmt.Println( user.Password)
2.gin的BindJSON() ShouldBindJSON() 区别
BindJSON():返回错误,并在header里面写400状态码。(多返回了http.StatusBadRequest)
// BindJSON is a shortcut for c.MustBindWith(obj, binding.JSON).
func (c *Context) BindJSON(obj any) error {
return c.MustBindWith(obj, binding.JSON)
}
func (c *Context) MustBindWith(obj any, b binding.Binding) error {
if err := c.ShouldBindWith(obj, b); err != nil {
c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) //nolint: errcheck
return err
}
return nil
}
ShouldBindJSON():只会返回错误信息,不会往header中写400的错误状态码。(没有状态码,多了个默认参数b为JSON)
// ShouldBindJSON is a shortcut for c.ShouldBindWith(obj, binding.JSON).
func (c *Context) ShouldBindJSON(obj any) error {
return c.ShouldBindWith(obj, binding.JSON)
}
func (c *Context) ShouldBindWith(obj any, b binding.Binding) error {
return b.Bind(c.Request, obj)
}
3.其他
疑问: 类似的方法c.ShouldBind(),c.Bind,c.ShouldBind()等,有什么区别?
响应数据绑定方法:
c.Bind
c.BindJSON
c.BindXML
c.BindQuery
c.BindYAML
c.ShouldBind
c.ShouldBindJSON
c.ShouldBindXML
c.ShouldBindQuery
c.ShouldBindYAML
以上方法区别总结:
带should和不带should的,最大区别就是响应带不带状态码。
bind后不同的类型,比如JSON,XML.Query等,区别是b参数默认相应类型。
bind后不加任何,shouBind()方法可以根据请求中contentType的不同类型,采用不同的方式进行处理(无论是QueryString/PostForm/JSON数据)。
//内部根据Content-Type去解析
c.ShouldBind(obj interface{})
//内部替你传递了一个binding.JSON,对象去解析
c.ShouldBindJSON(obj interface{})
//解析哪一种绑定的类型,根据你的选择
c.ShouldBindWith(obj interface{}, b binding.Binding)
四种常见的POST数据提交方式:content-type值
application/x-www-form-urlencoded enctype不设置 浏览器原生form表单
enctype 设置为 multipart/form-data 表单上传文件
application/json 序列化后的 JSON 字符串
text/xml 提交xml文件
参考链接:https://imququ.com/post/four-ways-to-post-data-in-http.html
其实,还有之前接触的一种简单的响应,差点忽略,就是不绑定结构体,响应数据直接为c.String()的。
c.String()
c.JSON()
c.HTML()
c.XML()
c.YAML()
实例:
c.String(200, "%v", "Hello World")
c.JSON(200,gin.H{
"success":true,
"msg":"你好 gin",
})
r.LoadHTMLGlob("templates/*")
c.HTML(200, "index.html", gin.H{
"time": "20xx年x月x日",
"location": "xx市",
"weather": "晴",
})
/templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{{.time}}<br>
{{.location}}<br>
{{.weather}}
</body>
</html>
总结小点
1.gin.H
gin.H
实际上就是 map[string]interface{}
的缩写
源码中为:
// H is a shortcut for map[string]any
type H map[string]any
c.JSON(http.StatusOK, map[string]interface{}{ "status": "登录成功"}) // 标准库写法
// 等价于
c.JSON(http.StatusOK, gin.H{ "status": "登录成功"}) // gin
3.接收请求->查数据库的大致过程
router: 路由对应处理函数。
r.POST("create", controlor.Create)
controlor:处理函数层 主要校验参数,构造响应数据
func Create(c *gin.Context) {
newId, err := service.Create(&input, c)
data := response.User{
Id: newId,
}
response.SuccessWithData(data, c)
}
service:服务层,主要调用多个model中的方法,查找多张数据表,组合返回数据。
func (u *User) Create(user *model.User, c *gin.Context) (newId uint, err error) {
newId = model.CreateUser()
return
}
model:数据层,查找对应表的各种方法。
type User struct {
NewId int `json:new_id`
}
func CreateUser() error {
// 查数据库
query := db.Model(&User{})
query = query.Select(查找条件)
return 结果
}