Gin
下载gin框架
go get -u github.com/gin-gonic/gin
下载失败的话配置一下goproxy
关闭GOSUMDB
go env -w GOSUMDB=off
更换源
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
下载后,再执行代码可能可能会报,binding.go文件中any,undefined any
尝试将Gin框架更新到最新版本
go get -u github.com/gin-gonic/gin
如果问题仍然存在,切换到稳定的版本,再go.mod
文件中指定版本
require github.com/gin-gonic/gin v1.6.3
案例
下载go get github.com/thinkerou/favicon
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
import "github.com/thinkerou/favicon"
func main() {
// 创建服务
ginServer := gin.Default()
// 修改图标
ginServer.Use(favicon.New("./火影忍者.png"))
// 访问地址
ginServer.GET("/hello", func(context *gin.Context) {
context.JSON(200, gin.H{"msg": "Hello Wold"})
})
ginServer.POST("/user", func(context *gin.Context) {
context.JSON(http.StatusOK, gin.H{"msg": "post"})
})
// 服务器端口
ginServer.Run(":8082")
}
获取参数
获取querystring参数
querystring
指的是URL中?
后面携带的参数,例如:/user/search?username=Lin&password=123456
。 获取请求的querystring参数的方法如下:
func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
r.GET("/user/search", func(c *gin.Context) {
// 可以添加默认值,当query返回为空时,Lin作为默认值
username := c.DefaultQuery("username", "Lin")
//username := c.Query("username")
password := c.Query("password")
//输出json结果给调用方
c.JSON(http.StatusOK, gin.H{
"message": "ok",
"username": username,
"password": password,
})
})
r.Run()
}
获取form参数
请求的数据通过form表单来提交,例如向/user/search
发送一个POST请求,获取请求数据的方式如下:
func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
r.POST("/user/search", func(c *gin.Context) {
// DefaultPostForm取不到值时会返回指定的默认值
//username := c.DefaultPostForm("username", "Lin")
username := c.PostForm("username")
password := c.PostForm("password")
//输出json结果给调用方
c.JSON(http.StatusOK, gin.H{
"message": "ok",
"username": username,
"password": password,
})
})
r.Run(":8080")
}
获取path参数
请求的参数通过URL路径传递,例如:/user/search/Lin/
。 获取请求URL路径中的参数的方式如下。
func main() {
//Default返回一个默认的路由引擎
r := gin.Default()
r.GET("/user/search/:username/:password", func(c *gin.Context) {
username := c.Param("username")
password := c.Param("password")
//输出json结果给调用方
c.JSON(http.StatusOK, gin.H{
"message": "ok",
"username": username,
"password": password,
})
})
r.Run(":8080")
}
参数绑定
func main() {
// 创建服务
ginServer := gin.Default()
ginServer.Use(favicon.New("./火影忍者.png"))
type Login struct {
User string `form:"user"`
Password string `form:"password"`
}
// 绑定JSON的示例 ({"user": "Lin", "password": "123456"})
ginServer.POST("/loginJSON", func(context *gin.Context) {
var login Login
if err := context.ShouldBindJSON(&login); err == nil {
fmt.Printf("login info:%v\n", login)
context.AbortWithStatusJSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
context.AbortWithStatusJSON(http.StatusBadRequest, err.Error())
}
})
// 绑定form表单示例 (user=q1mi&password=123456)
ginServer.POST("/loginForm", func(context *gin.Context) {
var login Login
if err := context.ShouldBind(&login); err == nil {
fmt.Printf("login info:%v\n", login)
context.AbortWithStatusJSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
context.AbortWithStatusJSON(http.StatusBadRequest, err.Error())
}
})
// 绑定QueryString示例 (/loginQuery?user=Lin&password=123456)
ginServer.GET("/loginForm", func(context *gin.Context) {
var login Login
if err := context.ShouldBindQuery(&login); err == nil {
fmt.Printf("login info:%v\n", login)
context.AbortWithStatusJSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
context.AbortWithStatusJSON(http.StatusBadRequest, err.Error())
}
})
ginServer.Run(":8082")
}
重定向
HTTP重定向
r.GET("/test", func(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, "http://www.sogo.com/")
})
路由重定向
r.GET("/test", func(c *gin.Context) {
// 指定重定向的URL
c.Request.URL.Path = "/test2"
r.HandleContext(c)
})
r.GET("/test2", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"hello": "world"})
})
中间件
定义中间件
// StatCost 是一个统计耗时请求耗时的中间件
func StatCost() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
c.Set("name", "Lin") // 可以通过c.Set在请求上下文中设置值,后续的处理函数能够取到该值
// 调用该请求的剩余处理程序
c.Next()
// 不调用该请求的剩余处理程序
// c.Abort()
// 计算耗时
cost := time.Since(start)
log.Println(cost)
}
}
注册中间件
为全局路由注册
func main() {
// 新建一个没有任何默认中间件的路由
r := gin.New()
// 注册一个全局中间件
r.Use(StatCost())
r.GET("/test", func(c *gin.Context) {
name := c.MustGet("name").(string) // 从上下文取值
log.Println(name)
c.JSON(http.StatusOK, gin.H{
"message": "Hello world!",
})
})
r.Run()
}
为某个路由单独组测
// 给/test2路由单独注册中间件(可注册多个)
r.GET("/test2", StatCost(), func(c *gin.Context) {
name := c.MustGet("name").(string) // 从上下文取值
log.Println(name)
c.JSON(http.StatusOK, gin.H{
"message": "Hello world!",
})
})
为路由组注册
shopGroup := r.Group("/shop", StatCost())
{
shopGroup.GET("/index", func(c *gin.Context) {...})
...
}
shopGroup := r.Group("/shop")
shopGroup.Use(StatCost())
{
shopGroup.GET("/index", func(c *gin.Context) {...})
...
}