GOGin

Posted 一曲长歌一剑天涯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GOGin相关的知识,希望对你有一定的参考价值。

参考资料
[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的头中。

以上是关于GOGin的主要内容,如果未能解决你的问题,请参考以下文章

gogin安装

从java到GoGin框架整合并部署Vue

从java到GoGin框架整合并部署Vue

GoGin从入门到精通-哪有那么多为什么

GoGin从入门到精通-哪有那么多为什么

GoGin从入门到精通—搭建MVC项目结构学习路由配置