给大家的福利
零基础入门
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
同时每个成长路线对应的板块都有配套的视频提供:
因篇幅有限,仅展示部分资料
网络安全面试题
绿盟护网行动
还有大家最喜欢的黑客技术
网络安全源码合集+工具包
所有资料共282G,朋友们如果有需要全套《网络安全入门+黑客进阶学习资源包》,可以扫描下方二维码领取(如遇扫码问题,可以在评论区留言领取哦)~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
)
func main() {
r := gin.Default()
r.GET(“/user/:name/:action”, func(c *gin.Context) {
name := c.Param(“name”) // 使用Param可以获取路由URL里面的数据
action := c.Param(“action”)
c.String(http.StatusOK, name+" rush “+action)
})
_ = r.Run(”:8000")
}
* 获取表单参数,一般用于`POST`,`PUT`请求。
Gin提供了`.PostForm`方法获取Form表单的值。
package main
import (
“fmt”
“github.com/gin-gonic/gin”
“net/http”
)
func main() {
r := gin.Default()
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静态文件
### 给大家的福利
**零基础入门**
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
![](https://img-blog.csdnimg.cn/img_convert/95608e9062782d28f4f04f821405d99a.png)
同时每个成长路线对应的板块都有配套的视频提供:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a91b9e8100834e9291cfcf1695d8cd42.png#pic_center)
因篇幅有限,仅展示部分资料
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**