〇、前言
本文将会写一个前后端分离的的小项目,本文将会只实现后端。

一、定义全局变量与模型
本文需要一个数据库,因此将这个数据库定义为全局变量将会非常轻松。
1 2 3 4 5 6 7 8 9 10
| var ( DB *gorm.DB )
type Todo struct { ID int `json:"id"` Title string `json:"title"` Status bool `json:"status"` }
|
二、建立数据库
1 2
| database create bubble; use bubble;
|
可以看到,已经创建了 一个名为bubble的mysql数据库:

三、连接数据库
在 gorm 框架下,对于 mysql 等多种数据库的使用极其方便:
1 2 3 4 5 6 7 8 9 10
| func initMySQL() (err error) { dsn := "root:pwd@tcp(127.0.0.1:3306)/bubble?charset=utf8mb4&parseTime=True&loc=Local" DB, err = gorm.Open("mysql", dsn) if err != nil { return err } return DB.DB().Ping() }
|
四、载入前端静态文件
部署一个项目,假设前端可靠,那么就可以放心得写后端了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| err := initMySQL() if err != nil { panic(err) } DB.AutoMigrate(&Todo{}) defer func(DB *gorm.DB) { err := DB.Close() if err != nil { panic(err) } }(DB)
r := gin.Default() r.Static("/static", "/Users/***/GoLand/gin_practice/chap18/static") r.LoadHTMLGlob("/Users/***/GoLand/gin_practice/chap18/templates/*") r.GET("/bubble", func(c *gin.Context) { c.HTML(http.StatusOK, "index.html", nil) })
|
五、路由组的实现
我们可以根据前端的各种请求,写一个路由组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| v1Group := r.Group("v1") { v1Group.POST("/todo", func(c *gin.Context) {
}) v1Group.GET("/todo", func(c *gin.Context) {
}) v1Group.GET("/todo/:id", func(c *gin.Context) {
}) v1Group.PUT("/todo/:id", func(c *gin.Context) {
}) v1Group.DELETE("/todo/:id", func(c *gin.Context) {
})
}
|
六、功能的实现
添加事项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| v1Group.POST("/todo", func(c *gin.Context) { var todo Todo c.BindJSON(&todo) if err := DB.Create(&todo).Error; err != nil { c.JSON(http.StatusOK, gin.H{ "err": err.Error(), }) return } else { c.JSON(http.StatusOK, todo) }
})
|
查询事项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| v1Group.GET("/todo", func(c *gin.Context) { var todoList []Todo if err = DB.Find(&todoList).Error; err != nil { c.JSON(http.StatusOK, gin.H{ "err": err.Error(), }) return } else { c.JSON(http.StatusOK, todoList)
} })
|
修改事项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| v1Group.PUT("/todo/:id", func(c *gin.Context) { id, ok := c.Params.Get("id") if !ok { c.JSON(http.StatusOK, gin.H{ "error": "id不存在", }) return } var todo Todo if err = DB.Where("id=?", id).First(&todo).Error; err != nil { c.JSON(http.StatusOK, gin.H{ "err": err.Error(), }) return
} c.BindJSON(&todo) if err = DB.Save(&todo).Error; err != nil { c.JSON(http.StatusOK, gin.H{ "error": err.Error(), }) return
} c.JSON(http.StatusOK, todo) })
|
删除事项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| v1Group.DELETE("/todo/:id", func(c *gin.Context) { id, ok := c.Params.Get("id") if !ok { c.JSON(http.StatusOK, gin.H{ "error": "id不存在", }) return } var todo Todo if err = DB.Where("id=?", id).Delete(&todo).Error; err != nil { c.JSON(http.StatusOK, gin.H{ "err": err.Error(), }) return } c.JSON(http.StatusOK, todo) })
|
这样,就完成了整个项目的后端处理。
七、运行起来的样子
点击运行,可以看到一个还算清爽的界面(前端写得好,与我无瓜):

添加几个事项:

查看一下数据库:

可以看到,数据库成功地将前端提交的表达做了持久化存储。再标记几个已完成:

再看看数据库:

可以看到成功地将 status 标记成了 1。撤销看看:

数据库:

删除看看:

数据库:

可以看到,后端的功能都正常。
全文完,感谢阅读。