在go的web项目中,gin相当于java中的springmvc、gorm相当于java中的mybatis、gomod相当于java中的maven。
gin的中文文档
我们新建一个文件夹,在当前文件夹下打开cmd,输入共go mod (默认项目名为文件夹名,也可以自己指定项目名)
go mod后会在当前目录下生成go.mod文件,记录项目所下载的外部依赖(这个就相当于java中maven项目中pom文件)
电脑安装配置git(已安装,直接忽略)
go get -u github.com/gin-gonic/gin
package main
import (
// 引入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",
})
})
}
我们在项目中新建文件夹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了
如果我们的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页面了
func main() {
r := gin.Default()
// gin.H 是map[string]interface{}的缩写 map键是string格式,值是任意格式
r.GET("/someJSON", func(c *gin.Context) {
// 方式一:自己拼接JSON
c.JSON(http.StatusOK, gin.H{"message": "Hello world!"})
})
r.GET("/moreJSON", func(c *gin.Context) {
// 方法二:使用结构体
var msg struct {
Name string `json:"user"` //使用标签 返回的数据Name修改为user
Message string
Age int
}
msg.Name = "小王"
msg.Message = "Hello world!"
msg.Age = 18
c.JSON(http.StatusOK, msg)
})
r.Run(":8080")
}
打开浏览器访问就可以看到{ “user”:“小王”,“Message”:“Hello world!”,“Age”:18}
请求的参数通过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")
}
为了能够更方便的获取请求相关参数,提高开发效率,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 Login
if 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会按照下面的顺序解析请求中的数据完成绑定:
r.GET("/test", func(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, "http://www.三体.com/")
})
r.GET("/hello", func(c *gin.Context) {
// 指定重定向的URL
c.Request.URL.Path = "/hello2"
r.HandleContext(c)
})
r.GET("/hello2", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"hello": "world"})
})
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()
}