目录
🧡Gin简介
🧡Gin特性
🧡Gin环境搭建
🧡HTTP请求和参数解析
创建Engine
Handle方法处理
Engine分类处理
表单实体绑定
ShouldBindQuery
ShouldBind
JSON
多数据格式返回请求结果
[]byte切片
string
JSON
HTML
路由分组
🧡中间件的使用
💟这里是CS大白话专场,让枯燥的学习变得有趣!
💟没有对象不要怕,我们new一个出来,每天对ta说不尽情话!
💟好记性不如烂键盘,自己总结不如收藏别人!
🧡Gin简介
💌Gin 是一个 golang 的微框架,封装比较优雅,API 友好,源码注释比较明确,已经发布了1.0版本。具有快速灵活,容错方便等特点。其实对于 golang 而言,web 框架的依赖要远比 Python,Java 之类的要小。自身的 net/http 足够简单,性能也非常不错。框架更像是一些常用函数或者工具的集合。借助框架开发,不仅可以省去很多常用的封装带来的时间,也有助于团队的编码风格和形成规范。
🍠Gin 框架是开源的,可以在 github 上下载其源码库,查看相应的说明:Gin源码库地址
🍠Gin 框架有一个官方网站,有对 Gin 相关的介绍和学习资料:Gin官网
🧡Gin特性
🍠速度:Gin 之所以被很多企业和团队所采用,第一个原因是因为其速度快,性能表现出众。
🍠中间件:和 iris 类似,gin 在处理请求时,支持中间件操作,方便编码处理。
🍠路由:在 gin 中可以非常简单地实现路由,路由组解析功能。
🍠内置渲染:Gin 支持 JSON、XML 和 HTML 等多种数据格式的渲染,并提供方便的操作 API。
🧡Gin环境搭建
💌gin 框架需要 go 语言版本在1.6及以上。可以通过 go version 查看 go 语言版本是否符合要求。
通过go get命令安装gin框架:
go get -u github.com/gin-gonic/gin
💌安装完毕后,可以在当前系统的 $GOPATH 目录下的 src/github.com 目录中找到 gin-gonic 目录,该目录下存放的就是 gin 框架的源码。
🧡HTTP请求和参数解析
创建Engine
💌在 gin 框架中,Engine 被定义成为一个结构体,其中包含了路由组、中间件、页面渲染接口、框架配置设置等相关内容。两种创建方式如下所示:
engine1 = gin.Default()
engine2 = gin.New()
💌gin.Default() 内也调用 gin.New() 创建Engine实例,但会默认使用Logger和Recovery中间件。
🍠Logger 是负责进行打印并输出日志的中间件,方便开发者进行程序调试。
🍠Recovery 中间件的作用是如果程序执行过程中遇到 panic 中断了服务,Recovery 会恢复程序执行,并返回服务器500内部错误。
💌通常情况下,使用默认的 gin.Default() 创建 Engine 实例。
Handle方法处理
💌在 Engine 中可以使用 Handle 方法处理 HTTP 请求。Handle 方法包含三个参数,具体如下:
func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc)
🍠httpMethod:表示要处理的 HTTP 的请求类型,是 GET、POST、DELETE、OPTIONS、HEAD、PUT、TRACE、CONNECT 请求类型中的一种。
🍠relativePath:表示要解析的接口,由开发者进行定义。
🍠handlers:是处理对应的请求的代码的定义。
package mainimport ("fmt""github.com/gin-gonic/gin"
)func main() {engine := gin.Default()//GET//http://localhost:8080/hello?name=Jodieengine.Handle("GET", "/hello", func(context *gin.Context) {path := context.FullPath()fmt.Println(path)//获取name值,若没有则返回strangername := context.DefaultQuery("name", "stranger")fmt.Println(name)//页面显示内容context.Writer.Write([]byte("Hello, " + name))})//POST//http://localhost:8080/loginengine.Handle("POST", "/login", func(context *gin.Context) {fmt.Println(context.FullPath())username := context.PostForm("username")password := context.PostForm("password")fmt.Println(username)fmt.Println(password)context.Writer.Write([]byte("Hello, " + username))})engine.Run()
}

Engine分类处理
💌除了 Engine 中包含的通用的处理方法以外,Engine 还可以按类型直接解析。Engine 中包含有get方法、post方法、delet方法等与 HTTP 请求类型对应的方法。
package mainimport ("fmt""github.com/gin-gonic/gin"
)func main() {engine := gin.Default()//GETengine.GET("/hello", func(context *gin.Context) {path := context.FullPath()fmt.Println(path)name := context.Query("name")fmt.Println(name)context.Writer.Write([]byte("Hello, " + name))})//POSTengine.POST("/login", func(context *gin.Context) {fmt.Println(context.FullPath())username, existName := context.GetPostForm("username")if existName {fmt.Println(username)}password, existWord := context.GetPostForm("password")if existWord {fmt.Println(password)}context.Writer.Write([]byte("Hello, " + username))})//DELETEengine.DELETE("/user/:id", func(context *gin.Context) {userID := context.Param("id")fmt.Println(userID)context.Writer.Write([]byte("DELETE " + userID))})engine.Run()
}
表单实体绑定
💌使用 PostForm 这种单个获取属性和字段的方式,代码量较多,需要一个一个属性进行获取。而表单数据的提交,往往对应着完整的数据结构体定义,其中对应着表单的输入项。gin 框架提供了数据结构体和表单提交数据绑定的功能,提高表单数据获取的效率。如下所示:
以用户注册功能为例,假设用户注册提交表单数据包含三项:username、phone 和 password。
type UserRegister struct {Username string `form:"username" binding:"required"`Phone string `form:"phone" binding:"required"`Password string `form:"password" binding:"required"`
}
创建了 UserRegister 结构体用于接收表单数据,通过 tag 标签的方式设置每个字段对应的 form 表单中的属性名,通过 binding 设置属性是否必须。
ShouldBindQuery
package mainimport ("fmt""github.com/gin-gonic/gin""log"
)func main() {engine := gin.Default()//GET//http://localhost:8080/hello?username=Jodie&password=1234engine.GET("/hello", func(context *gin.Context) {fmt.Println(context.FullPath())var user Usererr := context.ShouldBindQuery(&user)if err != nil {log.Fatal(err.Error())return}fmt.Println(user.Username)fmt.Println(user.Password)context.Writer.Write([]byte("Hello, " + user.Username))})engine.Run()
}type User struct {Username string `form:"username" binding:"required"`Password string `form:"password" binding:"required"`
}


ShouldBind
package mainimport ("fmt""github.com/gin-gonic/gin""log"
)func main() {engine := gin.Default()//POSTengine.POST("/regist", func(context *gin.Context) {fmt.Println(context.FullPath())var register UserRegistererr := context.ShouldBind(®ister)if err != nil {log.Fatal(err.Error())return}fmt.Println(register.Username)fmt.Println(register.Phone)context.Writer.Write([]byte("Hello, " + register.Username))})engine.Run()
}type UserRegister struct {Username string `form:"username" binding:"required"`Phone string `form:"phone" binding:"required"`Password string `form:"password" binding:"required"`
}
JSON
package mainimport ("fmt""github.com/gin-gonic/gin""log"
)func main() {engine := gin.Default()//POSTengine.POST("/addUser", func(context *gin.Context) {fmt.Println(context.FullPath())var person Personcontext.BindJSON(&person)err := context.BindJSON(&person)if err != nil {log.Fatal(err.Error())return}fmt.Println(person.Username)context.Writer.Write([]byte("Add " + person.Username))})engine.Run()
}type Person struct {Username string `form:"username" binding:"required"`Phone string `form:"phone" binding:"required"`Password string `form:"password" binding:"required"`
}
💌JSON格式提交请求:
{"username":"Nike""phone":"13265496230""password":"1234"
}
多数据格式返回请求结果
[]byte切片
💌通过 context.Writer.Write([]byte(返回结果)) 实现,前文内容已经使用,Writer 是 gin 框架中封装的一个 ResponseWriter 接口类型。
string
💌ResponseWriter 还封装了 WriteString 方法返回数据,通过 context.Writer.WriteString(返回结果) 实现。
package mainimport ("fmt""github.com/gin-gonic/gin"
)func main() {engine := gin.Default()//byte[]engine.GET("/hellobyte", func(context *gin.Context) {path := "请求路径:" + context.FullPath()fmt.Println(path)context.Writer.Write([]byte(path))})//stringengine.GET("/hellostring", func(context *gin.Context) {path := "请求路径:" + context.FullPath()fmt.Println(path)context.Writer.WriteString(path)})engine.Run()
}

JSON
💌JSON 格式规范使用的更为普遍,context 包含的 JSON 方法可以将结构体类型的数据转换成 JSON 格式的结构化数据,然后返回给客户端。
package mainimport ("fmt""github.com/gin-gonic/gin"
)func main() {engine := gin.Default()engine.GET("/hellojson", func(context *gin.Context) {path := "请求路径:" + context.FullPath()fmt.Println(path)//200:正常 404:NOT FOUND 500:内部错误//map类型context.JSON(200, map[string]interface{}{"code": 1,"message": "OK","data": path,})})//struct类型engine.GET("/hellostruct", func(context *gin.Context) {path := "请求路径:" + context.FullPath()fmt.Println(path)resp := Response{Code: 1, Message: "OK", Data: path}context.JSON(200, &resp)})engine.Run()
}type Response struct {Code intMessage stringData interface{}
}


HTML
package mainimport ("fmt""github.com/gin-gonic/gin""net/http"
)func main() {engine := gin.Default()//设置html目录engine.LoadHTMLGlob("./html/*")//静态文件目录engine.Static("/img", "./img")engine.GET("/hellohtml", func(context *gin.Context) {path := "请求路径:" + context.FullPath()fmt.Println(path)context.HTML(http.StatusOK, "index.html", gin.H{"path": path,"title": "Hello!",})})engine.Run()
}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>{{.title}}</title>
</head>
<body>
{{.path}}
<div><img src="../img/Miku.jpeg"></div>
</body>
</html>

路由分组
💌路由组是 router.Group 中的一个方法,用于对请求进行分组,相同模块的功能接口,可以使用路由组进行分类处理。
package mainimport ("fmt""github.com/gin-gonic/gin"
)func main() {engine := gin.Default()routerGroup := engine.Group("/user")routerGroup.POST("/register", registerHandle)routerGroup.DELETE("/:id", deleteHandle) engine.Run()
}func registerHandle(context *gin.Context) {path := "用户注册:" + context.FullPath()fmt.Println(path)context.Writer.WriteString(path)
}func deleteHandle(context *gin.Context) {path := "用户删除:" + context.FullPath()userID := context.Param("id")fmt.Println(path + " " + userID)context.Writer.WriteString(path + " " + userID)
}
🧡中间件的使用
💌在实际的业务开发和处理中,会有更复杂的业务和需求场景。一个完整的系统可能要包含鉴权认证、权限管理、安全检查、日志记录等多维度的系统支持,对于系统中的所有业务都适用,可以将一些通用业务抽离出来单独进行开发,然后以插件化的形式进行对接。这种方式既保证了系统功能的完整,同时又有效地将具体业务和系统功能进行解耦,还可以达到灵活配置的目的。
💌自定义中间件有两条标准:
🍠类型为 func 函数
🍠返回值类型为 HandlerFunc
package mainimport ("fmt""github.com/gin-gonic/gin"
)func main() {engine := gin.Default()//engine.Use(RequestInfos()) //所有接口均可使用中间件engine.GET("/middle", func(context *gin.Context) {context.JSON(200, map[string]interface{}{"code": 1,"msg": context.FullPath(),})})//只有指定接口可以使用engine.GET("/only", RequestInfos(), func(context *gin.Context) {fmt.Println("中断操作")context.JSON(200, map[string]interface{}{"code": 2,"msg": context.FullPath(),})})engine.Run()
}// 打印请求信息的中间件
func RequestInfos() gin.HandlerFunc {return func(context *gin.Context) {path := context.FullPath()method := context.Request.Methodfmt.Println("请求路径:", path)fmt.Println("请求method:", method)context.Next() //中断操作,先执行主函数内容fmt.Println("状态码:", context.Writer.Status())}
}









