这是我参与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("本地文件目录"))