共计 9123 个字符,预计需要花费 23 分钟才能阅读完成。
参考资料
[1] gin 根本应用
[2] gin 牛逼的 context
[3] Gin 框架介绍及应用
[4] 学习笔记
1. 简介
Gin 是 Go 语言写的一个 web 框架,它具备运行速度快,分组的路由器,良好的解体捕捉和错误处理,十分好的反对中间件和 json。总之在 Go 语言开发畛域是一款值得好好钻研的 Web 框架,开源网址:https://github.com/gin-gonic/gin
在 Go 语言开发的 Web 框架中,有两款驰名 Web 框架别离是 Martini 和 Gin,两款 Web 框架相比拟的话,Gin 本人说它比 Martini 要强很多。
gin.Default() 创立路由
gin.DisableConsoleColor()禁用控制台色彩
gin.SetMode()设置 gin 模式。参数能够传递:gin.DebugMode、gin.ReleaseMode、gin.TestMode。
路由的办法为:假设咱们先创立一个路由
router := gin.Default()
获取的形式能够为:
router.GET("/someGet", getting)
router.POST("/somePost", posting)
router.PUT("/somePut", putting)
router.DELETE("/someDelete", deleting)
router.PATCH("/somePatch", patching)
router.HEAD("/someHead", head)
router.OPTIONS("/someOptions", options)
router.Group(s string)分组,s 为组名
一、第一个 gin 程序
官网给的一个示例程序
package main
import "github.com/gin-gonic/gin"
func main() {r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong",})
})
r.Run(":8080") // listen and serve on 0.0.0.0:8080
}
运行程序,在浏览器上拜访:http://127.0.0.1:8080/ping
c.String 用来返回字符串。
c.JSON 用来返回 Json。
gin 的性能不只是简略输入 Json 数据。它是一个轻量级的 WEB 框架,反对 RestFull 格调 API,反对 GET,POST,PUT,PATCH,DELETE,OPTIONS 等 http 办法,反对文件上传,分组路由,Multipart/Urlencoded FORM,以及反对 JsonP,参数解决等等性能,这些都和 WEB 严密相干,通过提供这些性能,使开发人员更不便地解决 WEB 业务。不同于 net/http 库的路由函数,gin 进行了封装,把 request 和 response 都封装到 gin.Context 的上下文环境。
二、疾速匹配参数
Gin 框架能够疾速的匹配参数
func main() {router := gin.Default()
router.GET("/user/:name/:password", HinHandler)
router.Run(":8081")
}
//HinHandler 解构传过来的 name 和 password
func HinHandler(c *gin.Context) {name := c.Param("name")
pwd := c.Param("password")
// 外部提供办法用来返回字符串
c.String(http.StatusOK, "你好 %s, 你的明码为 %s", name, pwd)
}
运行程序在浏览器上拜访:http://127.0.0.1:8081/user/hu…
三、Gin 获取一般 get 参数
func main() {
// 批改模式
gin.SetMode(gin.ReleaseMode)
//Default 办法创立一个路由 handler。router := gin.Default()
router.GET("/user", GetHandler)
router.Run(":8081")
}
//GetHandler 应用 get 形式获取对应键的值
func GetHandler(c *gin.Context) {name := c.DefaultQuery("name", "Guest") // 找不到 name 给它一个默认值 Guest
password := c.Query("password") // 找不到间接赋空
//GetQuery 返回两个参数,第一个是找到的对应键的值,第二个是是否找到 error 类型
id, exist := c.GetQuery("id")
if !exist {name = "the key is not exist"}
c.Data(http.StatusOK, "text/plain",
[]byte(fmt.Sprintf("get success! %s %s %s", name, password, id)))
}
运行程序在浏览器上拜访:
http://127.0.0.1:8081/user?na…
四、分组
// 分组
// 组内成员拜访为 http://127.0.0.1:8080/admin/...
v1 := router.Group("admin")
{
// 拜访为 http://127.0.0.1:8080/admin/ping
v1.GET("/ping", api.HelloPage)
v1.GET("/welcome", api.LoginHandler)
v1.GET("/getquery",api.GetHandler)
}
五、Gin 默认路由
咱们能够自定义 404 谬误
func main() {
// 批改模式
gin.SetMode(gin.ReleaseMode)
//Default 办法创立一个路由 handler。router := gin.Default()
// 设定申请 url 不存在的返回值
router.NoRoute(NoResponse)
router.GET("/user", GetHandler)
router.Run(":8081")
}
//NoResponse 申请的 url 不存在,返回 404
func NoResponse(c *gin.Context) {
// 返回 404 状态码
c.JSON(http.StatusNotFound, gin.H{
"status": 404,
"error": "404, page not exists!",
})
}
//GetHandler 应用 get 形式获取对应键的值
func GetHandler(c *gin.Context) {name := c.DefaultQuery("name", "Guest") // 找不到 name 给它一个默认值 Guest
password := c.Query("password") // 找不到间接赋空
//GetQuery 返回两个参数,第一个是找到的对应键的值,第二个是是否找到 error 类型
id, exist := c.GetQuery("id")
if !exist {name = "the key is not exist"}
c.Data(http.StatusOK, "text/plain",
[]byte(fmt.Sprintf("get success! %s %s %s", name, password, id)))
}
咱们去申请一个并不存在的 url:http://127.0.0.1:8081/us
六、Gin 获取一般 post 参数
我这里是应用 RESTClient 来模仿的,在 Firefox 上附加组件
func main() {
// 批改模式
gin.SetMode(gin.ReleaseMode)
//Default 办法创立一个路由 handler。router := gin.Default()
// 设定申请 url 不存在的返回值
router.NoRoute(NoResponse)
router.POST("/user", PostLoginHandler)
router.Run(":8081")
}
//NoResponse 申请的 url 不存在,返回 404
func NoResponse(c *gin.Context) {
// 返回 404 状态码
c.JSON(http.StatusNotFound, gin.H{
"status": 404,
"error": "404, page not exists!",
})
}
//PostLoginHandler 获取参数
func PostLoginHandler(c *gin.Context) {name := c.PostForm("name") // 找不到 name 间接返回 0 值
password := c.DefaultPostForm("password", "888") // 找不到 password 赋默认值
sec, ok := c.GetPostForm("second") // 判断是否能找到,找不到返回 false
c.String(http.StatusOK, "hello %s %s %s", name, password, sec)
log.Panicln(ok)
}
七、中间件 MiddleWare
留神,gin.Default() 默认是加载了一些框架内置的中间件的,而 gin.New() 则没有,依据须要本人手动加载中间件。
func MiddleWare(c *gin.Context) {fmt.Println("before request")
c.Next()}
func main() {
// 批改模式
gin.SetMode(gin.ReleaseMode)
//Default 办法创立一个路由 handler。router := gin.Default()
// 设定申请 url 不存在的返回值
router.NoRoute(NoResponse)
router.Use(MiddleWare)
router.GET("/user", GetHandler)
router.Run(":8081")
}
//NoResponse 申请的 url 不存在,返回 404
func NoResponse(c *gin.Context) {
// 返回 404 状态码
c.JSON(http.StatusNotFound, gin.H{
"status": 404,
"error": "404, page not exists!",
})
}
//GetHandler 应用 get 形式获取对应键的值
func GetHandler(c *gin.Context) {name := c.DefaultQuery("name", "Guest") // 找不到 name 给它一个默认值 Guest
password := c.Query("password") // 找不到间接赋空
//GetQuery 返回两个参数,第一个是找到的对应键的值,第二个是是否找到 error 类型
id, exist := c.GetQuery("id")
if !exist {name = "the key is not exist"}
c.Data(http.StatusOK, "text/plain",
[]byte(fmt.Sprintf("get success! %s %s %s", name, password, id)))
}
咱们拜访下面的 url
在终端上你会发现中间件已执行,咱们能够在中间件里做验证或者⽇志记录
c.Next() 继续执行上面的函数
c.Abort() 截断执行
八、文件服务
上传单个文件
func main() {router := gin.Default() // Set a lower memory limit for multipart forms (default is 32 MiB) // router.MaxMultipartMemory = 8 << 20 // 8 MiB router.POST("/upload", func(c *gin.Context) {
// single file
file, _ := c.FormFile("file")
log.Println(file.Filename)
// Upload the file to specific dst.
// c.SaveUploadedFile(file, dst)
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
})
router.Run(":8080")
}
上传多个文件
func main() {router := gin.Default() // Set a lower memory limit for multipart forms (default is 32 MiB) // router.MaxMultipartMemory = 8 << 20 // 8 MiB router.POST("/upload", func(c *gin.Context) {// Multipart form form, _ := c.MultipartForm() files := form.File["upload[]"] for _, file := range files {log.Println(file.Filename)
// Upload the file to specific dst.
// c.SaveUploadedFile(file, dst)
}
c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
})
router.Run(":8080")
}
更多应用能够去 Github 去查:https://github.com/gin-gonic/gin
context 是杜 gin 最重要的局部。例如,它容许咱们在中间件之间传递变量、治理流、验证申请的 JSON 并出现 JSON 响应。type Context struct {
writermem responseWriter
Request *http.Request
Writer ResponseWriter
Params Params
handlers HandlersChain
index int8
engine *Engine
Keys map[string]interface{} //Keys 是一个专门用于每个申请上下文的键 / 值对。Errors errorMsgs //Errors 是附加到应用此上下文的所有处理程序 / 中间件的谬误列表。Accepted []string //Accepted 定义用于内容协商的手动承受格局列表。}
上下文创立
func (c *Context) reset() // 重置各个字段
func (c *Context) Copy() *Context // Copy 返回可在申请范畴外平安应用的以后上下文的正本。当必须将上下文传递给 goroutine 时,必须应用此办法。func (c *Context) HandlerName() string //HandlerName 返回主处理程序的名称。若处理程序是“handleGetUsers()”,则返回 main.handleGetUsers".
func (c *Context) HandlerNames() []string // HandlerNames 依照 HandlerName()的语义,按降序返回此上下文的所有已注册处理程序的列表
流量管制
func (c *Context) Next() // Next 应该只在中间件外部应用。它执行调用处理程序内链中挂起的处理程序。请参阅 GitHub 中的示例。func (c *Context) IsAborted() bool // 如果以后上下文被停止,IsAborted 将返回 true。func (c *Context) Abort() // 停止阻止调用挂起的处理程序。请留神,这不会进行以后处理程序。func (c *Context) AbortWithStatus(code int) //AbortWithStatus 调用“Abort()”,并用指定的状态代码写入标头。谬误治理
func (c *Context) Error(err error) *Error //Error 将谬误附加到以后上下文。推送到谬误列表。元数据管理
#### **2. *gin.Context**
func (c *Context) Set(key string, value interface{}) // Set 用于专门为该上下文此存储新的键 / 值。它如果以前没有应用过,lazy 还会初始化 c.Keys。func (c *Context) Get(key string) (value interface{}, exists bool) // Get 返回给定键的值,即:(value,true)。如果该值不存在,则返回(nil,false)func (c *Context) MustGet(key string) interface{} // MustGet 返回给定键的值(如果存在),否则会死机。func (c *Context) GetString(key string) (s string) // GetString 以字符串模式返回与键关联的值。func (c *Context) GetBool(key string) (b bool) //GetBool 以布尔值的模式返回与键关联的值。func (c *Context) GetInt(key string) (i int) //GetInt 以整数模式返回与键关联的值。func (c *Context) GetInt64(key string) (i64 int64) //GetInt64 以整数模式返回与密钥关联的值。func (c *Context) GetFloat64(key string) (f64 float64) //GetFloat64 将与键关联的值作为 float64 返回。func (c *Context) GetTime(key string) (t time.Time) //GetTime 返回与键关联的值 time。func (c *Context) GetDuration(key string) (d time.Duration) //GetDuration 返回与键关联的值作为持续时间。func (c *Context) GetStringSlice(key string) (ss []string) //GetStringSlice 以字符串片段的模式返回与键关联的值。func (c *Context) GetStringMap(key string) (sm map[string]interface{})//GetStringMap 以接口映射的模式返回与键关联的值。func (c *Context) GetStringMapString(key string) (sms map[string]string)//GetStringMapString 返回与键关联的值作为字符串映射。func (c *Context) GetStringMapStringSlice(key string) (smss map[string][]string)//GetStringMapStringSlice 返回与键关联的值,作为字符串片段的映射。输出数据
func (c *Context) Param(key string) string //Param 返回 URL 参数的值。这是 c 的捷径, 按名称参数(键)func (c *Context) Query(key string) string //Query 返回键控 url 查问值(如果存在),否则返回空字符串“(”)”。func (c *Context) DefaultQuery(key, defaultValue string) string //DefaultQuery 返回键控 url 查问值(如果存在), 否则,它将返回指定的 defaultValue 字符串。func (c *Context) GetQuery(key string) (string, bool)//GetQuery 与 Query()相似,如果存在 `(value,true)`(即便值是空字符串),则返回带键的 url 查问值,否则返回 `(”“,false)`。func (c *Context) get(m map[string][]string, key string) (map[string]string, bool) //get 是一个外部办法,返回满足条件的映射。func (c *Context) FormFile(name string) (*multipart.FileHeader, error) //FormFile 返回所提供表单密钥的第一个文件。func (c *Context) MultipartForm() (*multipart.Form, error) //MultipartForm 是解析的多局部表单,包含文件上传。func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error //SaveUploadedFile 将表单文件上载到特定的 dst。func (c *Context) Bind(obj interface{}) error //Bind 查看内容类型以主动抉择绑定引擎,依据“内容类型”标头,应用不同的绑定:“application/json”-->json 绑定, 否则 --> 返回谬误。func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error//MustBindWith 应用指定的绑定引擎绑定传递的构造指针。func (c *Context) BindJSON(obj interface{}) error //BindJSON 是 c.MustBindWith 的一种.
func (c *Context) ShouldBind(obj interface{}) error //ShouldBind 查看内容类型以主动抉择绑定引擎
func (c *Context) Status(code int) // 状态设置 HTTP 响应代码。func (c *Context) GetHeader(key string) string //GetHeader 从申请头返回值。func (c *Context) GetRawData() ([]byte, error) //GetRawData 返回流数据。func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool)//SetCookie 将 Set Cookie 头增加到 ResponseWriter 的头中。