Gin 学习笔记 02-Gin 响应和请求

AI-摘要
Yuan GPT
AI初始化中...
介绍自己 🙈
生成本文简介 👋
推荐相关文章 📖
前往主页 🏠
前往爱发电购买
Gin 学习笔记 02-Gin 响应和请求
SEAlencehe响应
json 响应
对Response 封装
package res
import "github.com/gin-gonic/gin"
type Response struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data any `json:"data"`
}
var codeMap = map[int]string{
1001: "权限错误",
1002: "角色错误",
1003: "参数错误",
}
func response(context *gin.Context, code int, data any, msg string) {
context.JSON(200, Response{
Code: code,
Msg: msg,
Data: data,
})
}
func Ok(context *gin.Context, data any, msg string) {
response(context, 0, data, msg)
}
func OkWithData(context *gin.Context, data any) {
Ok(context, data, "操作成功")
}
func OkWithMsg(context *gin.Context, msg string) {
Ok(context, gin.H{}, msg)
}
// 错误的封装
func Fail(context *gin.Context, code int, data any, msg string) {
response(context, code, data, msg)
}
func FailWithMsg(context *gin.Context, msg string) {
response(context, 1001, nil, msg)
}
func FailWithCode(context *gin.Context, code int) {
msg, ok := codeMap[code]
if !ok {
msg = "服务错误"
}
response(context, code, nil, msg)
}
response是唯一的实际出口,所有 HTTP 状态码都固定写200(enter.go:12),把”业务状态”和”HTTP 状态”分离——HTTP 永远 200,业务成功失败靠code字段表达。这是 RESTful 风格之外另一种常见约定(国内项目很流行)。业务代码只调
Ok/Fail,不直接碰response,保证所有响应都走同一个出口,不会有人偷偷返回不一样的格式。只关心数据 →
OkWithData(c, user)自动填”操作成功”只关心提示 →
OkWithMsg(c, "删除成功")自动填空data
好处:handler 代码更短、更聚焦业务,不用每次都手写 msg。这是”语法糖”,没有它们用 Ok 也能做到,但写了能少敲很多字。
package main
import (
"gin_study/study_response/res"
"github.com/gin-gonic/gin"
)
func main() {
//初始化
r := gin.Default()
//绑定路由
r.GET("/login", func(context *gin.Context) {
res.OkWithMsg(context, "成功")
})
r.GET("/users", func(context *gin.Context) {
res.OkWithData(context, map[string]any{
"name": "张三",
"age": 18,
})
})
r.POST("/users", func(context *gin.Context) {
res.FailWithMsg(context, "失败")
})
//绑定端口运行
r.Run(":8080")
}
html 响应
使用LoadHTMLGlob加载一个目录下的所有html文件
也可以使用LoadHTMLFiles加载单个html文件
load之后,下面才能用这个文件名
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
// 加载模板 只有这里加载了模板,下面才能用
r.LoadHTMLGlob("templates/*")
//r.LoadHTMLFiles("templates/index.html")
r.GET("", func(c *gin.Context) {
c.HTML(200, "index.html", nil)
})
r.Run(":8080")
}
HTML的第三个参数是可以向HTML中传递数据
但是现在都是前后端分离的时代了,也很少使用后端返回模板了,知道怎么用就好
c.HTML(200, "index.html", map[string]any{
"title": "这是网页标题",
})
html文件中使用
<title>{{.title}}</title>
其实借助这个功能,可以很方便的修改网站的标题和logo
响应文件
用于浏览器直接请求这个接口唤起下载
c.Header("Content-Type", "application/octet-stream") // 表示是文件流,唤起浏览器下载,一般设置了这个,就要设置文件名
c.Header("Content-Disposition", "attachment; filename=3.文件下载.go") // 用来指定下载下来的文件名
c.File("3.文件下载.go")
- 要设置Content-Type,唤起浏览器下载
- 只能是get请求
前端请求后端接口,然后唤起浏览器下载
c.Header("fileName", "xxx.png")
c.Header("msg", "文件下载成功")
c.File("uploads/12.png")
最好的做法
调下载接口的请求,后端不返回实际文件内容,而是生成一个临时下载地址
前端构造a标签,再请求这个接口唤起浏览器下载
静态文件
r.Static("st" /*别名*/, "static")// 第一个参数是别名,第二个才是实际路径
//http://localhost:8080/st/hello.txt
r.StaticFile("abc", "static/hello.txt")
//http://localhost:8080/abc
静态文件的路径,不能再被路由使用了
请求
查询参数
?key=xxx&name=xxxx&name=yyyy 这种就被称为查询参数
查询参数不是GET请求专属的
r.GET("", func(c *gin.Context) {
name := c.Query("name")
age := c.DefaultQuery("age", "25")
keyList := c.QueryArray("key")
fmt.Println(name, age, keyList)
})
//http://localhost:8080/?name=zhangsan&age=18&key=123&key=333
zhangsan 18 [123 333]
动态参数
用户的个人信息页面,他的路径
/users?id=123 // 查询参数的模式
/users/123 // 动态参数模式
r.GET("users/:id/:name", func(c *gin.Context) {
userId := c.Param("id")
userName := c.Param("name")
fmt.Println(userId, userName)
})
表单参数
form 表单
r.POST("users", func(c *gin.Context) {
name := c.PostForm("name")
//通过 ok 来判断是否传了数据
age, ok := c.GetPostForm("age")
fmt.Println(name, age, ok)
})
文件上传
r.POST("users", func(c *gin.Context) {
fileHeader, err := c.FormFile("file")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(fileHeader.Filename) //文件名
fmt.Println(fileHeader.Size) //单位是字节
file, _ := fileHeader.Open()
byteData, _ := io.ReadAll(file)
err = os.WriteFile("xxx.jpg", byteData, 0666)
fmt.Println(err)
})
简单的方法
err = c.SaveUploadedFile(fileHeader, "uploads/"+fileHeader.Filename)
fmt.Println(err)
多文件
r.POST("users", func(c *gin.Context) {
form, err := c.MultipartForm()
if err != nil {
fmt.Println(err)
return
}
for _, headers := range form.File {
for _, header := range headers {
c.SaveUploadedFile(header, "uploads/muilt/"+header.Filename)
}
}
})
接口测试工具
Postman
apifox
注意:接口测试工具能走通的,前端请求不一定可以走通
- get请求带请求体
- ws加请求头
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果

