Golang之gin简单使用 | 8月更文挑战

3,143 阅读3分钟

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

简介

Gin是一个使用Go开发的web框架,简洁,性能好,开箱即用,方便扩展。

一个最简单的服务器例子。

func main() {
   //创建实例
   engine := gin.Default()
   //处理路由
   engine.GET("/", func(context *gin.Context) {
      //以字符串格式返回
      context.String(200, "这就是一个普通的字符串")
   })
   //运行服务器,默认监听8080端口
   engine.Run()
}

Run()方法默认是以HTTP的方式运行,使用RunTLS()会以HTTPS的方式运行。

运行模式

gin.SetMode(gin.ReleaseMode)

gin有三种模式:debug,release,test。

gin中提供了对应的常量。gin.DebugMode  ReleaseMode   TestMode。

创建框架实例

gin.Default()或者gin.New()

Default()包含Logger和recovery中间件,New()是不包含任何中间件的。

新手建议使用Default()生成实例,熟手使用New()用来定制化中间件。

路由

Engine实现了net/http中的Handler接口。

Engine的GET、POST等待方法是标准的Restful API。

//第一个参数是路由路径,第二个参数是一个回调函数。
//Context是一个结构体,用来获取HTTP消息,并返回消息。
g.GET("", func(context *gin.Context) {

})

分组路由

v1 :=engine.Group("/v1")
{
  v1.GET("/hehe",handleFunc)
  v1.GET("/xixi",handleFunc)

}

错误路由

Engine.NoRoute(handleFunc())

获取请求(Request)

所有的操作主要都在Context中。

//获取请求路径
context.Request.URL.Path 
//客户端ip,以IPv6形式返回。使用net.ParseIP("ip").Tov4().String()转换成ipv4.
context.ClientIP()
//请求类型
context.Request.Method

获取Header

context.Request.Header.Get("Header中的字段,比如Content-Type")

获取路径中的参数

func main() {
    router := gin.Default()

    // 此规则能够匹配/user/john这种格式,但不能匹配/user/ 或 /user这种格式
    router.GET("/user/:name", func(c *gin.Context) {
            name := c.Param("name")
            c.String(http.StatusOK, "Hello %s", name)
    })

    // 但是,这个规则既能匹配/user/john/格式也能匹配/user/john/send这种格式
    // 如果没有其他路由器匹配/user/john,它将重定向到/user/john/
    router.GET("/user/:name/*action", func(c *gin.Context) {
            name := c.Param("name")
            action := c.Param("action")
            message := name + " is " + action
            c.String(http.StatusOK, message)
    })

    router.Run(":8080")
}

获取GET参数

注意:监听的路径必须是/path/:name,才能获取name。

//如果输入的是/path/james?sex=man

//获取URL参数名.
name := context.Param("name") //name = james

//获取URL中查询参数的值.
sex := context.Query("sex") //sex = man

//查询参数不存在,返回默认值
work := context.DefaultQuery("work", "unknown") //work = unknown

获取POST参数

//获取表单中的数据
file := context.PostForm("file")
age := context.PostForm("age")

//文件上传
multipartForm, err := context.MultipartForm()
if err != nil {
   return
}
//获取文件和其他参数
file := multipartForm.File["filename"]
age := multipartForm.Value["age"]


//bind()只能解析Content-type为application/json或者xml的数据
people := struct {
   Name    string
   Age int
}{}
//必须传入指针,否则出错
err := context.Bind(&people)
if err != nil {
   fmt.Println("解析失败....")
}

Bind(interface{}) error

会根据请求的不同Content-Type,内部使用不同的bind方式,如果是application/json,会调用BindJson(...),其他同理。

如果传递的是JSON数据,请求时必须将Content-Type设置为applicatioin/json,提交数据的格式也需要为Json格式,不然不会以JSON的方式解析。

如果想要获取以form-data(表单)提交的数据,只需要在struct中给字段加上form标签就行,和json一样。

想同时兼容2种提交,同时加上json和form标签即可。

常见返回错误:invalid character '-' in numeric literal

这是因为请求传入的数据格式和服务器定义的格式不一样,导致解析失败。比如需要Json,客户端使用的是form-data表单提交,所以失解析失败。

返回结果(Response)

设置Header

context.Header("key","value")

设置全局信息

可以随时通过context.Get()来取值。相当于全局变量了。

context.Set("key",interface{})

返回信息

//会自动把struct转换为json,struct需要struct字段首字母必须大写才能被导出。
contex.JSON(http.StatusOK,struct)

gin.H是一个Map,一般和JSON()方法配合使用。

//以json返回,gin.H是一个Map
context.JSON(http.StatusOK,gin.H{"code":0,"message":"this is a result"})
//以字符串返回
context.String(http.StatusOK,"this is a message")

设置静态文件

r := gin.Default()

//文件目录
r.static("访问路径","映射的本地路径")

//单个文件
r.staticFile("访问路径","映射的本地文件路径")

//文件系统,意思就是能在web上访问文件系统。
r.staticFS("访问路径",http.Dir("本地文件目录"))