【Go开源宝藏】Web框架 GIN 专场 (含思维导图) 持续更新_gin开发路线图(1)

r.POST("/form", func(c \*gin.Context) {
	username := c.PostForm("username")
	password := c.PostForm("password")
	c.String(http.StatusOK, fmt.Sprintf("username:%s,password:%s", username, password))
})
\_ = r.Run(":8000")

}


### 1.4 文件上传与下载


#### 1.4.1 上传


* 提供了`.FormFile`来获取文件



package main

import (
“github.com/gin-gonic/gin”
)

func main() {
r := gin.Default()
r.POST(“/upload”, func(c *gin.Context) {
file, err := c.FormFile(“file”) // file是参数名称
if err != nil {
c.String(500, “上传图片出错”) //出错就会返回这个
}
c.SaveUploadedFile(file, file.Filename) // 保存文件
c.String(http.StatusOK, file.Filename) // 返回状态码
})
_ = r.Run(“:8000”)
}


#### 1.4.2 下载


### 1.5 路由拆分


我们一般来说,会把这个路由拆分成`URL`和`处理函数`。这样能高效管理我们的框架逻辑。



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

func helloHandler(c *gin.Context) { // 把处理函数放在这里,可以处理一些复杂的业务
c.JSON(http.StatusOK, gin.H {
“message”: “Hello World!”, // 通过这个 gin.H{} 进行json格式的返回
})
}

// Router 配置路由信息
func Router() *gin.Engine {
r := gin.Default()
r.GET(“/hello”, helloHandler) // 这样这个路由就比较简洁了。
return r
}


## 2. 数据绑定


### 2.1 json数据格式


* 定义接收数据的结构体


`binding:"required"`修饰的字段,是必须有的,没有是会报错的。后面可以跟着限制,`满足限制`才不会报错。



type Product struct {
Name string form:"name" json:"name"
CategoryID int form:"category\_id" json:"category\_id"
Title string form:"title" json:"title" binding:"required,min=2,max=100"
Info string form:"info" json:"info" binding:"max=1000"
ImgPath string form:"img\_path" json:"img\_path"
Price string form:"price" json:"price"
DiscountPrice string form:"discount\_price" json:"discount\_price"
OnSale string form:"on\_sale" json:"on\_sale"
Num string form:"num" json:"num"
}


`gin`框架中提供了一个`ShouldBindJSON`方法,这样就能可以把`json格式`解析到`结构体`中。



func helloHandler(c *gin.Context) { // 把处理函数放在这里,可以处理一些复杂的业务
var data Product
if err := c.ShouldBindJSON(&data); err != nil {
// 进行数据的绑定,这样传过来的数据就会传入这个data当中
// gin.H封装了生成json数据的工具
c.JSON(http.StatusBadRequest, gin.H{“error”: err.Error()}) // 返回错误信息
return
}
c.JSON(http.StatusOK, gin.H{“status”: “200”})
}

// Router 配置路由信息
func Router() *gin.Engine {
r := gin.Default()
r.GET(“/hello”, helloHandler) // 这样这个路由就比较简洁了。
return r
}


### 2.2 form表单数据


同样的我们使用`2.1`中的`Product结构体`,注意一定要在结构体中,用`tags`标志`form`格式


上面的那个Product结构体是用tags标志了form格式和json格式的,所以两个都能用。



func helloHandler(c *gin.Context) { // 把处理函数放在这里,可以处理一些复杂的业务
var data Product
if err := c.Bind(&data); err != nil {
// Bind()默认解析并绑定form格式,这样传过来的数据就会传入这个data当中
c.JSON(http.StatusBadRequest, gin.H{“error”: err.Error()}) // 返回错误信息
return
}
c.JSON(http.StatusOK, gin.H{“status”: “200”})
}


### 2.3 URI



type Product struct {
Name string form:"name" json:"name" uri:"name”
CategoryID int form:"category\_id" json:"category\_id" uri:"category\_id"
Title string form:"title" json:"title" uri:“title binding:"required,min=2,max=100"
Info string form:"info" json:"info" uri:“info binding:"max=1000"
ImgPath string form:"img\_path" json:"img\_path" uri:"img\_path"
Price string form:"price" json:"price" uri:“price
DiscountPrice string form:"discount\_price" json:"discount\_price" uri:"discount\_price"
OnSale string form:"on\_sale" json:"on\_sale" uri:"on\_sale"
Num string form:"num" json:"num" uri:"num"
}


gin中提供了`ShouldBindUri`方法进行绑定



func helloHandler(c *gin.Context) { // 把处理函数放在这里,可以处理一些复杂的业务
var data Product
if err := c.ShouldBindUri(&data); err != nil {
c.JSON(http.StatusBadRequest, gin.H{“error”: err.Error()}) // 返回错误信息
return
}
c.JSON(http.StatusOK, gin.H{“status”: “200”})
}



> 
> 无论是`ShouldBindJSON`还是`Bind`还是`ShouldBindUri`  
>  不过我个人比较喜欢用`c.ShouldBind()`这种,看个人喜欢吧~
> 
> 
> 


## 3. 参数验证


### 3.1 普通情况



type User struct {
Phone string form:"phone" binding:"required,gt=10" //不能为空并且大于10
Name string form:"name" binding:"required"
Birthday time.Time form:"birthday" time\_format:"2006-01-02"
// 满足格式才能接收,减少了if-else的判断
}


### 3.2 自定义情况


使用 `gopkg.in/go-playground/validator.v8` 包


* 在结构体上,绑定这个`NotNullAndAdmin`。



type User struct {
Phone string form:"phone" binding:"required,gt=10" //不能为空并且大于10
Name string form:"name" binding:"NotNullAndAdmin" // 自定义一个验证
Birthday time.Time form:"birthday" time\_format:"2006-01-02"
// 满足格式才能接收,减少了if-else的判断
}


* 编写自定义方法



func nameNotNullAndAdmin(v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
if value, ok := field.Interface().(string); ok {
return value != “” && !(“admin” == value)// 字段不能为空,并且不等于 admin
}
return true
}


* 把我们的自定义注册到`validator`中就好了



if v, ok := binding.Validator.Engine().(\*validator.Validate); ok {
	\_ = v.RegisterValidation("NotNullAndAdmin", nameNotNullAndAdmin)  //注册定义的验证方法
}

## 4. 渲染


### 4.1 数据的响应


* Json 前后端主流的交互数据格式,我自己也是经常用这个。



func main() {
r := gin.Default()
r.GET(“/json”,JsonHandler)
_ = r.Run(“:8000”)
}

func JsonHandler(c *gin.Context) {
c.JSON(200, gin.H{“message”: “HelloJson”, “status”: 200})
}


* Struct



func main() {
r := gin.Default()
r.GET(“/struct”, StructHandler)
_ = r.Run(“:8000”)
}

func StructHandler(c *gin.Context) {
var msg struct {
Name string
Message string
Number int
}
msg.Name = “FanOne”
msg.Message = “Golang”
msg.Number = 10001
c.JSON(200, msg)
}


* XML



func main() {
r := gin.Default()
r.GET(“/xml”, XMLHandler)
_ = r.Run(“:8000”)
}

func XMLHandler(c *gin.Context) {
c.XML(200, gin.H{“message”: “HelloXml”})
}


* YAML



func main() {
r := gin.Default()
r.GET(“/yaml”, YAMLHandler)
_ = r.Run(“:8000”)
}

func YAMLHandler(c *gin.Context) {
c.YAML(200, gin.H{“message”: “HelloYaml”})
}


* ProtoBuf 这几年很火的数据格式



func main() {
r := gin.Default()
r.GET(“/protobuf”, ProtoBufHandler)
_ = r.Run(“:8000”)
}

func ProtoBufHandler(c *gin.Context) {
reps := []int64{int64(1), int64(2)}
// 定义数据
label := “label”
// 传protobuf格式数据
data := &protoexample.Test{
Label: &label,
Reps: reps,
}
c.ProtoBuf(200, data)
}


### 4.2 模板渲染



> 
> * gin支持加载HTML模板, 然后根据模板参数进行配置并返回相应的数据,本质上就是字符串替换
> * `LoadHTMLGlob()`方法可以加载模板文件
> * `Static`方法可以加载静态文件
> 
> 
> 


* 加载HTML模板



func main() {
r := gin.Default()
r.LoadHTMLGlob(“tempate/*”) // 加载你的模板文件 就是html文件嗷
r.GET(“/index”, func(c *gin.Context) {
c.HTML(http.StatusOK, “index.html”, gin.H{“msg”: “HelloWorld”, “status”: “200”})
})
r.Run()
}


* 加载Static静态文件



func main() {
r := gin.Default()
r.Static(“/assets”, “./assets”) // 需要定义一个静态文件目录
r.GET(“/index”, func(c *gin.Context) {
c.HTML(http.StatusOK, “index.html”, gin.H{“msg”: “HelloWorld”, “status”: “200”})
})
r.Run()
}


这两个其实很少用,因为基本都是前后端分离,所以就很少去用这些东西哒。


使用了这些意味着前后页面也在后端这边,高度耦合,所以不推荐使用嗷~


### 4.3 重定向


`gin`包中有`c.Redirect`可以使得跳转的时候重新跳到 `baidu.com` 这个页面



func main() {
r := gin.Default()
r.GET(“/index”, func(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, “http://www.baidu.com”)
})
r.Run()
}


## 5. 中间件


这里会单独出一些中间件的介绍的,当然只是我自己经常用的到一些而已。


* CORS
* JWT-Go
* Logging
* …


## 6. 会话控制


### 6.1 Cookie


* HTTP是`无状态协议`,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出。
* Cookie就是`解决HTTP协议无状态的方案`之一,中文是小甜饼的意思。
* Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求。
* Cookie由服务器创建,并发送给浏览器,最终由`浏览器保存`。
* 服务端发送cookie给客户端,客户端请求时携带cookie


Cookie的问题有很多,比如说`不安全`,`明文`,`增加带宽消耗`,`cookie有上限`等等。


### 6.2 Sessions


Session是另一种记录客户状态的机制,不同的是Cookie保存在`客户端浏览器`中,而Session保存在`服务器`上。


客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在`服务器`上。这就是`Session`。


客户端浏览器再次访问时只需要从该`Session`中查找该客户的状态就可以了。



"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"

为自定义session后端提供cookie和文件系统session以及基础结构。


主要功能是:


* 简单的API:将其用作设置签名(以及可选的加密)cookie的简便方法。
* 内置的后端可将`session`存储在`cookie`或`文件系统中`。
* Flash消息:一直持续读取的`session值`。
* 切换session持久性(又称“记住我”)和设置其他属性的便捷方法。
* `旋转身份验证`和`加密密钥`的机制。
* 每个请求有多个session,即使是使用不同的后端也是如此。
* 自定义`session后端`的接口和`基础结构`:可以使用通用`API检索`并批量保存来源不同的session。



store := cookie.NewStore([]byte("something-very-secret"))  // 存储

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以点击这里获取
安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
[外链图片转存中…(img-zvupA7MS-1714769690553)]
[外链图片转存中…(img-kHkC5iFB-1714769690554)]
[外链图片转存中…(img-yAebDUPD-1714769690554)]
[外链图片转存中…(img-il8OMlWX-1714769690555)]
[外链图片转存中…(img-mN2sb2GM-1714769690555)]
[外链图片转存中…(img-FMmdQtv3-1714769690556)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以点击这里获取

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值