golang-gin框架

导包

go get -u github.com/gin-gonic/gin

如果导包失败则检查是否更改了goproxy,原先的goproxy被墙了。

go env -w GOPROXY=https://goproxy.cn,direct   //配置GOPROXY,永久生效

fresh热加载

热加载:在每次代码更改保存的时候自动重启项目。

go install github.com/pilu/fresh@latest

执行后会在GOPATH/bin下面生成fresh.exe,之后则可以用fresh代替go run main.go。

如果在命令行输入fresh时,出现:

fresh : 无法将“fresh”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
需要将GOPATH/bin路径加入到系统环境变量PATH中。

发送请求案例

DELETE、PUT同理

func main() {
	engine := gin.Default() //创建引擎
	//配置路由 
	engine.GET("/", func(c *gin.Context) {
		c.JSON(200, gin.H{"name": "yi"})//这里也可以输入一个结构体类型
	})
	engine.POST("/w", func(c *gin.Context) {
		c.String(200, "hello %s", "u")
	})
	
	engine.Run(":8080")
}

其中gin.H是map[string]any的别名

URL参数查询

GET请求参数

url为: http://localhost:8080/?name=yi&age=18

engine.GET("/", func(c *gin.Context) {
		name := c.Query("name")
		age := c.DefaultQuery("age", "20")//如果参数中没有age,则age为20
		c.JSON(http.StatusOK, gin.H{
			"name": name,
			"age":  age,
		})
	})

POST请求参数

前端代码:点击提交按钮后,会向/doAddUser发送携带表单数据的post请求。

<form action="/doAddUser" method="post">
	姓名<input type="text" name="username">
	密码<input type="password" name="password">
	<input type="submit" value="提交">
form>

获取前端中表单的输入:

engine.POST("/doAddUser", func(c *gin.Context) {
		username := c.PostForm("username")
		password := c.PostForm("password")
		age := c.DefaultPostForm("age", "20")//获取不到则默认为20
		c.JSON(http.StatusOK, gin.H{
			"username": username,
			"password": password,
			"age":age,
		})
	})

请求参数绑定到结构体(POST请求同理)

GET请求地址:http://localhost:8080/pwd?name=yi&age=1

engine.GET("/pwd", func(c *gin.Context) {
		type Student struct {
			Name string `json:"name" form:"name"`
			Age  int    `form:"age"`
		}
		var stu Student
		if err := c.ShouldBind(&stu); err != nil {
			c.JSON(http.StatusOK, gin.H{
				"err": err,
			})
		} else {
			fmt.Println(stu)
			c.JSON(http.StatusOK, stu)
		}
	})

需要注意:绑定的结构体字段需要大写(用到了反射机制),并且要带上form标签。
form标签表示从请求/表单获取数据时对应的字段。
json标签表示结构体转化为json时的字段名,c.JSON(Status,stu)会返回{name:“yi”,Age:“1”}

解析 POST raw-xml数据

engine.POST("/xml", func(c *gin.Context) {
		type Article struct {
			Name string `xml:"name" json:"name"`
		}
		article:=Article{}
		rawData, _ := c.GetRawData()//从request.body中获取原始数据
		//将xml解析成结构体
		if err := xml.Unmarshal(rawData, &article);err!=nil{
			c.JSON(200,gin.H{"err":err})
		}else{
			c.JSON(200,article)
		}
	})

获取动态路由参数

请求地址:http://localhost:8080/lists/15

engine.GET("/lists/:id", func(c *gin.Context) {
		id := c.Param("id")  //id =15
		c.JSON(200, gin.H{"id": id})
	})

路由组

g := engine.Group("/admin")
	{
		g.GET("/v2", func(c *gin.Context) {
			c.String(200, "admin/v2")
		})
		g.GET("/v3", func(c *gin.Context) {
			c.String(200, "admin/v3")
		})
	}

项目分离

分为Controller、Routers、MiddleWare。
Controller(控制器):用于存放路由组的处理函数。func(c *gin.Context) {})
Routers:对路由组进行注册。

中间件

c.Next() 先去执行其他程序,最后返回来执行
c.Abort() 终止后继该请求的剩余处理程序,当前中间件仍然执行。
c.Set(“Key”,“Value”) 设置中间件共享变量
c.Get(“Key”) 获取中间件共享变量
engine.Use(middleWare) 注册全局中间件

gin.Default() 默认使用了Logger()、Recovery()中间件

中间件使用goroutine时,不能直接用c,要使用c.Copy(),不会影响客户端的响应。

计算API调用时间:

func CountTime(c *gin.Context) {
	start := time.Now()
	c.Next() //执行其他的中间件,最后返回来执行自己
	end := time.Now()
	println(end.Sub(start).String())
}
//......
g.GET("/v2",CountTime ,func(c *gin.Context) {
			time.Sleep(time.Second)
			c.String(200, "admin/v2")
})

文件上传

web代码:

 <form action="http://localhost:8080/admin/doAdd" method="post" enctype="multipart/form-data">
        用户名: <input type="text" name="username" > <br>
        头像 <input type="file" name="face" > <br>
        <input type="submit" value="提交">
   form>

gin代码:

func (AdminController) DoAdd(c *gin.Context) {
	username := c.PostForm("username")
	println(username)
	file, err := c.FormFile("face")
	if err != nil {
		log.Println(err)
	}
	println(file.Filename)
	//dst := path.Join("./", file.Filename) 
	c.SaveUploadedFile(file, "./"+file.Filename) //保存图片
}

Cookies

func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool)

  • name:cookie名称
  • value:cookie值
  • maxAge:生命周期,以秒为到位
  • path:路径
  • domain:能访问cookies的域名 可以用子域名 .xx.cn
  • secure:是否安全,true表示只支持https
  • httpOnly:cookies只能被http访问,不能被前端js等访问

Cookies与c.Set()的区别:
Cookies保存在客户的浏览器中,主要用于实现跨网页的数据共享操作,如登录信息保存、历史记录、购物车。而c.Set()用于跨中间件的数据共享,如该次操作的执行计时。

Session

Session是借助于Cookies将信息保存到服务器上。
1.第一次发起登录请求时,服务器会生成Session对象,其中包含SessionID用户信息。SessionID是Session对象的唯一标识符,通过SessionID可以找到指定的用户信息。
2.在浏览器写入Cookies,保存生成的SessionID。
3.客户端后续的请求都会携带含有SessionID的Cookie,也就是把SessionID传递给了服务端。服务端拿到之后,去查下该SessionID是否存在,如果没有就说明没有登录。如果有,就找到了这个用户的信息,可以继续后续的操作。

Gin框架中没有session的相关实现,所以需要依赖第三方库
https://github.com/gin-contrib/sessions

Cookies与Session的区别:

最大的区别:Session存在服务器上,Cookie直接把数据存在客户端上。带来的不同点有:

  • Session相对安全点,数据不会被篡改。SessionID校验失败就直接返回了。
  • Session可以存各种各样类型的数据。Cookie只能存字符串。Go服务中多数是直接存一个结构体。
  • Cookie有存储空间和数量上限。Session理论上没有任何上限。
    Session可以持久化到很多地方。比如数据库,缓存。

你可能感兴趣的:(中间件,golang,gin)