认识gin
go流行的web框架
go从诞生之初就带有浓重的开源属性,其原生库已经很强大,即使不依赖框架,也能进行高性能开发,又因为其语言并没有一定的设计标准,所以较为灵活,也就诞生了众多的框架,各具有特色,满足不同的喜好。
地址:https://github.com/gin-gonic/gin
go的框架其实可以理解为库,并不是用了某一个框架就不能用别的框架,可以选择性的使用各个库中的优秀组件,进行组合
gin介绍
Gin 是一个基于 Go 语言编写的 Web 框架,它提供了类似于 Martini 框架但性能更好的 API 服务。Gin 框架的主要特点包括:
- 高性能:Gin 使用了高性能的 httprouter 作为其底层的 HTTP 路由器,速度提升了近 40 倍。
- 易用性:Gin 提供了简单好用的核心上下文 Context,以及丰富的工具集,如 JSON/XML 响应、数据绑定与校验等。
- 路由与中间件:Gin 提供了优雅的路由/中间件系统,支持中间件传入的 HTTP 请求经由一系列中间件和最终操作来处理,例如 Logger、Authorization、GZIP 以及最终的 DB 操作。
- Crash 处理:Gin 框架可以捕获发生在 HTTP 请求中的 panic 并 recover 它,从而保证服务器始终可用。
- JSON 验证:Gin 框架可以解析并验证 JSON 格式的请求数据,例如检查某个必须值是否存在。
- 路由群组:Gin 支持通过路由群组来更好地组织路由,例如是否需要授权、设置 API 的版本等。
- 无限制的群组嵌套:Gin 支持无限制的路由群组嵌套,不会降低性能。
总之,Gin 是一个高效、易用且功能丰富的 Web 框架,适合用于开发高性能的 Web 应用程序。
gin的安装
首先进行开发环境的准备
mkdir ginlearn
先创建项目目录
进入目录 再使用go work init 命令初始化
go mod init test.com/helloworld
go work use ./helloworld
然后就可以使用go get命令下载gin框架
现在开发环境已经准备好了
第一个gin程序
在项目目录下新建一个main.go,并在里面写入以下代码:
package main
import (
"github.com/gin-gonic/gin"
"log"
)
func main() {
r := gin.Default()
//curl http://localhost:8080/hello 获取到json返回值
//{“name”:"hello world"}
r.GET("/hello", func(context *gin.Context) {
context.JSON(200, gin.H{
"name": "hello world",
})
})
err := r.Run(":8080")
if err != nil {
log.Fatal(err)
}
}
然后在浏览器里 访问 http://localhost:8080/hello 就可以看到以下内容
路由
路由是URI到函数的映射
一个URI含: http://localhost:8080/user/find?id=11
- 协议,比如http,https等
- ip端口或者域名,比如127.0.01:8080或者www.test.com
- path ,比如/path
- query,比如?query
同时访问的时候,还需要指明http method 比如get post 等
RESTful API规范
RESTful API的规范建议我们使用特定的HTTP方法来对服务器上的资源进行操作。
比如:
GET 表示读取服务器上的资源
POST 表示在服务器上的创建资源
PUT 表示更新或者替换服务器上的资源
DELETE 表示删除服务器上的资源
请求方法
r.GET("/get", func(ctx *gin.Context) {
ctx.JSON(200, "get")
})
r.POST("/save", func(ctx *gin.Context) {
ctx.JSON(200, "save")
})
r.PUT("/update", func(ctx *gin.Context) {
ctx.JSON(200, "update")
})
r.DELETE("/delete", func(ctx *gin.Context) {
ctx.JSON(200, "delete")
})
Any代表任意一种类型都支持
r.Any("/any", func(context *gin.Context) {
context.JSON(200,gin.H{
"name":"any",
})
URI
URI书写的时候,我们不需要关心scheme和authority这两部分,我们主要通过path和query两部分的书写来进行资源的定位。
- 静态url,比如/hello, /user/find
r.POST("/user/find",func(ctx *gin.Context){
})
- 路径参数 比如/user/find/:id
r.GET("/get/find/:id", func(ctx *gin.Context) {
ctx.JSON(200, ctx.Param("id"))
})
- 模糊匹配,比如/user/*path
r.GET("/get/*path", func(ctx *gin.Context) {
ctx.JSON(200, ctx.Param("path"))
})
处理函数
定义:
type HandlerFUnc func(*Context)
通过上下文的参数,获取http的请求参数,响应http请求等。
分组路由
在进行开发的时候,我们往往要进行模块的划分,比如用户模块,以user开发,商品模块,以goods开头。或者进行多版本开发,不同版本之间路径是一致的,这种时候,就可以用到分组路由了。
v1 := r.Group("/v1")
{
v1.GET("/find", func(ctx *gin.Context) {
ctx.JSON(200, "find")
})
v1.GET("/save", func(ctx *gin.Context) {
ctx.JSON(200, "save")
})
}
v2 := r.Group("/v2")
{
v2.GET("/find", func(ctx *gin.Context) {
ctx.JSON(200, "find")
})
v2.GET("/save", func(ctx *gin.Context) {
ctx.JSON(200, "save")
})
}
请求参数
GET请求参数
使用Get请求传参时,类似于这样http://localhost:8080/user/save?id=11&name=zhangsan
普通参数
request url : http://localhost:8080/user/save?id=11&name=zhangsan
参数后面的部分叫做Query
r.GET("/user/save", func(context *gin.Context) {
id := context.Query("id")
name := context.Query("name")
context.JSON(200, gin.H{
"id": id,
"name": name,
})
})
所以使用context.Query()函数就能获取该格式的参数
context.GetQuery()可以指明没有的参数:
r.GET("/user/save", func(context *gin.Context) {
id := context.Query("id")
name := context.Query("name")
address, ok := context.GetQuery("address")
context.JSON(200, gin.H{
"id": id,
"name": name,
"address": address,
"ok": ok,
})
})
context.DefaultQuery()可以设置默认值:
r.GET("/user/save", func(context *gin.Context) {
id := context.Query("id")
name := context.Query("name")
address := context.DefaultQuery("address", "beijing")
context.JSON(200, gin.H{
"id": id,
"name": name,
"address": address,
})
})
还有另一种方式获取到get请求中的参数 就是使用结构体与这种格式的请求参数进行绑定
首先需要声明一个结构体(需要先进行绑定)
type User struct {
Id int64 `form:"id""`
Name string `form:"name""`
}
然后在处理的GET请求中编写如下代码:
r.GET("/user/save", func(context *gin.Context) {
var user User
err := context.BindQuery(&user)
if err != nil {
log.Println(err)
}
context.JSON(200, user)
})
主要是通过context.BindQuery(&user)的方法与实例化出来的结构user进行绑定。
context.ShouldBindQuery(&user)会更高级一些
数组参数
请求url:http://localhost:8080/user/get/?address=Beijing&address=shanghai
都是address=xxx , 这里就需要用数组的形式去接收参数。
r.GET("/user/get", func(context *gin.Context) {
address := context.QueryArray("address")
context.JSON(200, address)
})