[ go 与 golang | 青训营笔记]
这是我参与「第五届青训营 」伴学笔记创作活动的第 9 天, 在学习了go的相关基础知识以后,可以说是初步的了解了go,接下来,我们将步入全新的环节,今天我们学习go的一个常用web框架gin
4. 请求方式
原始参数 GetRawData
form-data
x-www-form-urlencoded
json
{
"name": "枫枫",
"age": 21
}
func _raw(c *gin.Context) {
body, _ := c.GetRawData()
contentType := c.GetHeader("Content-Type")
switch contentType {
case "application/json":
// json解析到结构体
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
var user User
err := json.Unmarshal(body, &user)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println(user)
}
}
封装一个解析json到结构体上的函数
func bindJson(c *gin.Context, obj any) (err error) {
body, _ := c.GetRawData()
contentType := c.GetHeader("Content-Type")
switch contentType {
case "application/json":
err = json.Unmarshal(body, &obj)
if err != nil {
fmt.Println(err.Error())
return err
}
}
return nil
}
四大请求方式
GET` `POST` `PUT` `DELETE
Restful风格指的是网络应用中就是资源定位和资源操作的风格。不是标准也不是协议。
GET:从服务器取出资源(一项或多项)
POST:在服务器新建一个资源
PUT:在服务器更新资源(客户端提供完整资源数据)
PATCH:在服务器更新资源(客户端提供需要修改的资源数据)
DELETE:从服务器删除资源
// 以文字资源为例
// GET /articles 文章列表
// GET /articles/:id 文章详情
// POST /articles 添加文章
// PUT /articles/:id 修改某一篇文章
// DELETE /articles/:id 删除某一篇文章
package main
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
)
type ArticleModel struct {
Title string `json:"title"`
Content string `json:"content"`
}
type Response struct {
Code int `json:"code"`
Data any `json:"data"`
Msg string `json:"msg"`
}
func _bindJson(c *gin.Context, obj any) (err error) {
body, _ := c.GetRawData()
contentType := c.GetHeader("Content-Type")
switch contentType {
case "application/json":
err = json.Unmarshal(body, &obj)
if err != nil {
fmt.Println(err.Error())
return err
}
}
return nil
}
// _getList 文章列表页面
func _getList(c *gin.Context) {
// 包含搜索,分页
articleList := []ArticleModel{
{"Go语言入门", "这篇文章是《Go语言入门》"},
{"python语言入门", "这篇文章是《python语言入门》"},
{"JavaScript语言入门", "这篇文章是《JavaScript语言入门》"},
}
c.JSON(200, Response{0, articleList, "成功"})
}
// _getDetail 文章详情
func _getDetail(c *gin.Context) {
// 获取param中的id
fmt.Println(c.Param("id"))
article := ArticleModel{
"Go语言入门", "这篇文章是《Go语言入门》",
}
c.JSON(200, Response{0, article, "成功"})
}
// _create 创建文章
func _create(c *gin.Context) {
// 接收前端传递来的json数据
var article ArticleModel
err := _bindJson(c, &article)
if err != nil {
fmt.Println(err)
return
}
c.JSON(200, Response{0, article, "添加成功"})
}
// _update 编辑文章
func _update(c *gin.Context) {
fmt.Println(c.Param("id"))
var article ArticleModel
err := _bindJson(c, &article)
if err != nil {
fmt.Println(err)
return
}
c.JSON(200, Response{0, article, "修改成功"})
}
// _delete 删除文章
func _delete(c *gin.Context) {
fmt.Println(c.Param("id"))
c.JSON(200, Response{0, map[string]string{}, "删除成功"})
}
func main() {
router := gin.Default()
router.GET("/articles", _getList) // 文章列表
router.GET("/articles/:id", _getDetail) // 文章详情
router.POST("/articles", _create) // 添加文章
router.PUT("/articles/:id", _update) // 编辑文章
router.DELETE("/articles/:id", _delete) // 删除文章
router.Run(":80")
}
请求头相关
请求头参数获取
GetHeader,可以大小写不分,且返回切片中的第一个数据
router.GET("/", func(c *gin.Context) {
// 首字母大小写不区分 单词与单词之间用 - 连接
// 用于获取一个请求头
fmt.Println(c.GetHeader("User-Agent"))
//fmt.Println(c.GetHeader("user-agent"))
//fmt.Println(c.GetHeader("user-Agent"))
//fmt.Println(c.GetHeader("user-AGent"))
// Header 是一个普通的 map[string][]string
fmt.Println(c.Request.Header)
// 如果是使用 Get方法或者是 .GetHeader,那么可以不用区分大小写,并且返回第一个value
fmt.Println(c.Request.Header.Get("User-Agent"))
fmt.Println(c.Request.Header["User-Agent"])
// 如果是用map的取值方式,请注意大小写问题
fmt.Println(c.Request.Header["user-agent"])
// 自定义的请求头,用Get方法也是免大小写
fmt.Println(c.Request.Header.Get("Token"))
fmt.Println(c.Request.Header.Get("token"))
c.JSON(200, gin.H{"msg": "成功"})
})
响应头相关
设置响应头
// 设置响应头
router.GET("/res", func(c *gin.Context) {
c.Header("Token", "jhgeu%hsg845jUIF83jh")
c.Header("Content-Type", "application/text; charset=utf-8")
c.JSON(0, gin.H{"data": "看看响应头"})
})
5. 绑定
gin中的bind可以很方便的将 前端传递 来的数据与 结构体 进行 参数绑定 ,以及参数校验
参数绑定
在使用这个功能的时候,需要给结构体加上Tag json form uri xml yaml
Must Bind
不用,校验失败会改状态码
Should Bind
可以绑定json,query,param,yaml,xml
如果校验不通过会返回错误
ShouldBindJSON
package main
import "github.com/gin-gonic/gin"
type UserInfo struct {
Name string `json:"name"`
Age int `json:"age"`
Sex string `json:"sex"`
}
func main() {
router := gin.Default()
router.POST("/", func(c *gin.Context) {
var userInfo UserInfo
err := c.ShouldBindJSON(&userInfo)
if err != nil {
c.JSON(200, gin.H{"msg": "你错了"})
return
}
c.JSON(200, userInfo)
})
router.Run(":80")
}
ShouldBindQuery
绑定查询参数
tag对应为form
// ?name=枫枫&age=21&sex=男
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
type UserInfo struct {
Name string `json:"name" form:"name"`
Age int `json:"age" form:"age"`
Sex string `json:"sex" form:"sex"`
}
func main() {
router := gin.Default()
router.POST("/query", func(c *gin.Context) {
var userInfo UserInfo
err := c.ShouldBindQuery(&userInfo)
if err != nil {
fmt.Println(err)
c.JSON(200, gin.H{"msg": "你错了"})
return
}
c.JSON(200, userInfo)
})
router.Run(":80")
}
ShouldBindUri
绑定动态参数
tag对应为uri
// /uri/fengfeng/21/男
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
type UserInfo struct {
Name string `json:"name" form:"name" uri:"name"`
Age int `json:"age" form:"age" uri:"age"`
Sex string `json:"sex" form:"sex" uri:"sex"`
}
func main() {
router := gin.Default()
router.POST("/uri/:name/:age/:sex", func(c *gin.Context) {
var userInfo UserInfo
err := c.ShouldBindUri(&userInfo)
if err != nil {
fmt.Println(err)
c.JSON(200, gin.H{"msg": "你错了"})
return
}
c.JSON(200, userInfo)
})
router.Run(":80")
}
ShouldBind
会根据请求头中的content-type去自动绑定
form-data的参数也用这个,tag用form
默认的tag就是form
绑定form-data、x-www-form-urlencode
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
type UserInfo struct {
Name string `form:"name"`
Age int `form:"age"`
Sex string `form:"sex"`
}
func main() {
router := gin.Default()
router.POST("/form", func(c *gin.Context) {
var userInfo UserInfo
err := c.ShouldBind(&userInfo)
if err != nil {
fmt.Println(err)
c.JSON(200, gin.H{"msg": "你错了"})
return
}
c.JSON(200, userInfo)
})
router.Run(":80")
}