目录
- 前言
- gin的基本使用
- 1 创建项目,用于项目管理 go mod
- 2 下载安装gin(前提是电脑已经安装了git)
- gin示例
- 3 Gin渲染(返回给前端的数据)
- 3.1 返回html
- 3.2 加载静态资源
- 3.3 返回json格式数据
- 4 获取请求参数
- 4.1 获取path参数
- 4.2 ShouldBind()参数绑定,获取json,form,路径参数
- 5 重定向
- 5.1 http重定向
- 5.2 路由重定向
- 5.3 gin路由
- 普通路由
- 路由组
前言
在go的web项目中,gin相当于java中的springmvc、gorm相当于java中的mybatis、gomod相当于java中的maven。
gin的中文文档
gin的基本使用
1 创建项目,用于项目管理 go mod
我们新建一个文件夹,在当前文件夹下打开cmd,输入共go mod (默认项目名为文件夹名,也可以自己指定项目名)
go mod后会在当前目录下生成go.mod文件,记录项目所下载的外部依赖(这个就相当于java中maven项目中pom文件)
2 下载安装gin(前提是电脑已经安装了git)
电脑安装配置git(已安装,直接忽略)
go get -u github.com/gin-gonic/gin
gin示例
package mainimport (
// 引入gin包"github.com/gin-gonic/gin"
)func main() {// 创建一个默认的路由引擎r := gin.Default()// GET:请求方式;/hello:请求的路径// 当客户端以GET方法请求/hello路径时,会执行后面的匿名函数r.GET("/hello", func(c *gin.Context) {// c.JSON:返回JSON格式的数据给客户端c.JSON(200, gin.H{ // 状态码200 和 map类型数据"message": "Hello world!",})})// 启动HTTP服务,默认在0.0.0.0:8080启动服务r.Run()
}
将上面的代码保存并编译执行,然后使用浏览器打开localhost:8080/hello就能看到一串JSON字符串"message": “Hello world!”。
Gin支持RESTful API的开发
func main() {r := gin.Default()r.GET("/hello", func(c *gin.Context) {c.JSON(200, gin.H{"message": "GET",})})r.POST("/hello", func(c *gin.Context) {c.JSON(200, gin.H{"message": "POST",})})r.PUT("/hello", func(c *gin.Context) {c.JSON(200, gin.H{"message": "PUT",})})r.DELETE("/hello", func(c *gin.Context) {c.JSON(200, gin.H{"message": "DELETE",})})
}
3 Gin渲染(返回给前端的数据)
3.1 返回html
我们在项目中新建文件夹static,用于保存静态资源
然后把我们自定义的html文件放在static文件夹下(我这里叫hello.html)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>66666666666666666</h1>
</body>
</html>
Gin框架中使用LoadHTMLGlob()或者LoadHTMLFiles()方法进行HTML模板渲染。
func main() {// 加载默认引擎r := gin.Default()// 访问static下的所有文件r.LoadHTMLGlob("static/*")// 访问static下的单个文件//r.LoadHTMLFiles("static/hello.html")r.GET("/hello", func(c *gin.Context) {// 把hello.html返回给前端,并附带title信息c.HTML(http.StatusOK, "hello.html", gin.H{"title": "hello",})})// 运行在本机8080端口r.Run(":8080")
}
打开浏览器访问localhost:8080/hello,就可以看到html了
3.2 加载静态资源
如果我们的html文件有引入外部静态资源的请求,就需要用到Static函数了
例如
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>// 引入css文件 请求为“/css/index.css”<link rel="stylesheet" href="/css/index.css">
</head>
<body><h1>66666666666666666</h1>
</body>
</html>
我们需要在static目录下新建css文件index.css
修改go文件
func main() {// 加载默认引擎r := gin.Default()// 加载静态文件 (接收/css请求,让请求去static目录下找index.css文件)r.Static("/css","./static")// 访问static下的所有文件r.LoadHTMLGlob("static/*")// 访问static下的单个文件//r.LoadHTMLFiles("static/hello.html")r.GET("/hello", func(c *gin.Context) {// 把hello.html返回给前端,并附带title信息c.HTML(http.StatusOK, "hello.html", gin.H{"title": "hello",})})// 运行在本机8080端口r.Run(":8080")
}
浏览器访问,然后我们就可以看到带有css样式的html页面了
3.3 返回json格式数据
func main() {r := gin.Default()// gin.H 是map[string]interface{}的缩写 map键是string格式,值是任意格式r.GET("/someJSON", func(c *gin.Context) {// 方式一:自己拼接JSONc.JSON(http.StatusOK, gin.H{"message": "Hello world!"})})r.GET("/moreJSON", func(c *gin.Context) {// 方法二:使用结构体var msg struct {Name string `json:"user"` //使用标签 返回的数据Name修改为userMessage stringAge int}msg.Name = "小王"msg.Message = "Hello world!"msg.Age = 18c.JSON(http.StatusOK, msg)})r.Run(":8080")
}
打开浏览器访问就可以看到{ “user”:“小王”,“Message”:“Hello world!”,“Age”:18}
4 获取请求参数
4.1 获取path参数
请求的参数通过URL路径传递,例如:/user/search/王/shanghai。 获取请求URL路径中的参数的方式如下。
func main() {//Default返回一个默认的路由引擎r := gin.Default()r.GET("/user/search/:username/:address", func(c *gin.Context) {username := c.Param("username")address := c.Param("address")//输出json结果给调用方c.JSON(http.StatusOK, gin.H{"message": "ok","username": username,"address": address,})})r.Run(":8080")
}
4.2 ShouldBind()参数绑定,获取json,form,路径参数
为了能够更方便的获取请求相关参数,提高开发效率,gin基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryString、form表单、JSON、XML等参数到结构体中。.ShouldBind()能够基于请求自动提取JSON、form表单和QueryString类型的数据,并把值绑定到指定的结构体对象。
type Login struct {// 使用标签 如果是form请求,把User改为user,json请求改为user,是否必须User string `form:"user" json:"user" binding:"required"`Password string `form:"password" json:"password" binding:"required"`
}func main() {router := gin.Default()// 绑定JSON的示例 ({"user": "go", "pass": "123456"})router.POST("/loginJSON", func(c *gin.Context) {var login Loginif err := c.ShouldBind(&login); err == nil {fmt.Printf("login info:%#v\n", login)c.JSON(http.StatusOK, gin.H{"user": login.User,"pass": login.Password,})} else {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}})// 绑定form表单示例 (user=go&pass=123456)router.POST("/loginForm", func(c *gin.Context) {var login Login// ShouldBind()会根据请求的Content-Type自行选择绑定器if err := c.ShouldBind(&login); err == nil {c.JSON(http.StatusOK, gin.H{"user": login.User,"pass": login.Password,})} else {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}})// 绑定QueryString示例 (/login?user=go&pass=123456)router.GET("/loginForm", func(c *gin.Context) {var login Login// ShouldBind()会根据请求的Content-Type自行选择绑定器if err := c.ShouldBind(&login); err == nil {c.JSON(http.StatusOK, gin.H{"user": login.User,"pass": login.Password,})} else {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}})router.Run(":8080")
}
ShouldBind会按照下面的顺序解析请求中的数据完成绑定:
- 如果是 GET 请求,只使用 Form 绑定引擎(query)。
- 如果是 POST 请求,首先检查 content-type 是否为 JSON 或 XML,然后再使用 Form(form-data)。
5 重定向
5.1 http重定向
r.GET("/test", func(c *gin.Context) {c.Redirect(http.StatusMovedPermanently, "http://www.三体.com/")
})
5.2 路由重定向
r.GET("/hello", func(c *gin.Context) {// 指定重定向的URLc.Request.URL.Path = "/hello2"r.HandleContext(c)
})
r.GET("/hello2", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"hello": "world"})
})
5.3 gin路由
普通路由
r.GET("/index", func(c *gin.Context) {...})
r.GET("/login", func(c *gin.Context) {...})
r.POST("/login", func(c *gin.Context) {...})
一个可以匹配所有请求方法的Any方法如下:
r.Any("/test", func(c *gin.Context) {...})
为没有配置处理函数的路由添加处理程序,默认情况下它返回404代码,下面的代码为没有匹配到路由的请求都返回404.html页面。
r.NoRoute(func(c *gin.Context) {c.HTML(http.StatusNotFound, "404.html", nil)})
路由组
我们可以将拥有共同URL前缀的路由划分为一个路由组。习惯性一对{}包裹同组的路由,
func main() {r := gin.Default()userGroup := r.Group("/user"){userGroup.GET("/index", func(c *gin.Context) {...})userGroup.GET("/login", func(c *gin.Context) {...})userGroup.POST("/login", func(c *gin.Context) {...})}shopGroup := r.Group("/shop"){shopGroup.GET("/index", func(c *gin.Context) {...})shopGroup.GET("/cart", func(c *gin.Context) {...})shopGroup.POST("/checkout", func(c *gin.Context) {...})}r.Run()
}