gorm/gin框架实战
项目简介
学习源视频:【最新Go Web开发教程】基于gin框架和gorm的web开发实战 (七米出品)_哔哩哔哩_bilibili
本博客为我的学习笔记。
项目目标:实现一个备忘录工具(当然不支持alert),仅仅是可以记录待办事项。
实现了:添加待办项、删除待办项、完成待办项、查询待办项
项目主页展示:
添加、查询待办项展示:
删除待办项展示:
项目框架
可以看看之前同专栏的博客,这是一个很基本的框架
package mainimport ("fmt""github.com/gin-gonic/gin""github.com/jinzhu/gorm"_ "github.com/jinzhu/gorm/dialects/mysql""net/http"
)type Todo struct {ID int `json:"id"`Title string `json:"title"`Status bool `json:"status"`
}var (DB *gorm.DB
)func initMySQL() (err error) {}func main() {//连接数据库err := initMySQL()if err != nil {panic(err)}defer DB.Close() //关闭数据库连接//模型绑定DB.AutoMigrate(&Todo{})r := gin.Default()//设置静态资源文件r.Static("/static", "static")// 设置gin框架模版文件r.LoadHTMLGlob("templates/*")//设置路由r.GET("/", func(c *gin.Context) {c.HTML(http.StatusOK, "index.html", nil)})//设置路由组v1Group := r.Group("/v1"){//添加一个事项v1Group.POST("/todo", func(c *gin.Context) {})//查看一个事项v1Group.GET("/todo/:id", func(c *gin.Context) {})//查看所有事项v1Group.GET("/todo/", func(c *gin.Context) {})//修改一个事项v1Group.PUT("/todo/:id", func(c *gin.Context) {})//删除一个事项v1Group.DELETE("/todo/:id", func(c *gin.Context) {})}r.Run()
}
接口填充
数据库连接
DB, err = gorm.Open("mysql", "usr1:12345@tcp(***:3306)/db1?charset=utf8&parseTime=True&loc=Local")
if err != nil {panic(err)
}
return DB.DB().Ping()
添加一个事项
v1Group.POST("/todo", func(c *gin.Context) {//前端页面填写待办事项,点击提交,会发送请求到这//1.从请求中把数据拿出来var todo Todoc.BindJSON(&todo)fmt.Println(todo)//2.存入数据库 + 3.返回响应if err = DB.Create(&todo).Error; err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error(),})} else {c.JSON(http.StatusOK, todo)}
})
查看所有事项
//查看一个事项
v1Group.GET("/todo/:id", func(c *gin.Context) {//...一般用不到
})
//查看所有事项
v1Group.GET("/todo/", func(c *gin.Context) {var todoList []Todoif err = DB.Find(&todoList).Error; err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error(),})} else {fmt.Println(todoList)c.JSON(http.StatusOK, todoList)}
})
修改一个事项
//修改一个事项
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 Todoif err = DB.Where("id=?", id).First(&todo).Error; err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error(),})} else {c.BindJSON(&todo)if err = DB.Save(&todo).Error; err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error(),})} else {c.JSON(http.StatusOK, todo)}}
})
删除一个事项
//删除一个事项
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}if err = DB.Where("id=?", id).Delete(Todo{}).Error; err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error(),})} else {c.JSON(http.StatusOK, gin.H{id: "delete",})}
})
ApiPost接口测试
添加接口
查看接口
修改接口
删除接口
企业级项目划分
1.controller
控制器:控制路由进来后执行的函数
package controllerimport ("fmt""gin_demo_BubbleList/models""github.com/gin-gonic/gin""net/http"
)/*
url -> controller -> logic -> model
请求 -> 控制器 -> 业务逻辑 -> 模型层的增删改查
*/
func IndexHandler(c *gin.Context) {c.HTML(http.StatusOK, "index.html", nil)
}func Create(c *gin.Context) {//前端页面填写待办事项,点击提交,会发送请求到这//1.从请求中把数据拿出来var todo models.Todoc.BindJSON(&todo)fmt.Println(todo)//2.存入数据库 + 3.返回响应err := models.CreateTodo(&todo)if err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error(),})} else {c.JSON(http.StatusOK, todo)}//if err = DB.Create(&todo).Error; err != nil {// c.JSON(http.StatusOK, gin.H{// "error": err.Error(),// })//} else {// c.JSON(http.StatusOK, todo)//}
}func GetTodoList(c *gin.Context) {todoList, err := models.GetTodoList()if err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error(),})} else {fmt.Println(todoList)c.JSON(http.StatusOK, todoList)}//if err = DB.Find(&todoList).Error; err != nil {// c.JSON(http.StatusOK, gin.H{// "error": err.Error(),// })//} else {// fmt.Println(todoList)// c.JSON(http.StatusOK, todoList)//}
}func UpdateById(c *gin.Context) {id, ok := c.Params.Get("id")if !ok {c.JSON(http.StatusOK, gin.H{"error": "无效的id",})return}todo, err := models.GetTodoById(id)if err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error(),})return}//var todo Todo//if err = DB.Where("id=?", id).First(&todo).Error; err != nil {// c.JSON(http.StatusOK, gin.H{// "error": err.Error(),// })// return//}c.BindJSON(&todo)if err = models.UpdateTodoById(todo); err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error(),})} else {c.JSON(http.StatusOK, todo)}
}func DeleteById(c *gin.Context) {id, ok := c.Params.Get("id")if !ok {c.JSON(http.StatusOK, gin.H{"error": "无效的id",})return}err := models.DeleteTodo(id)if err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error(),})} else {c.JSON(http.StatusOK, gin.H{id: "delete",})}//if err = DB.Where("id=?", id).Delete(Todo{}).Error; err != nil {// c.JSON(http.StatusOK, gin.H{// "error": err.Error(),// })//} else {// c.JSON(http.StatusOK, gin.H{// id: "delete",// })//}
}
2.models
模具:模型+业务逻辑(ps:可以分开)
package modelsimport ("gin_demo_BubbleList/dao"
)type Todo struct {ID int `json:"id"`Title string `json:"title"`Status bool `json:"status"`
}// Todo 增删改查
// CreateTodo 创建一个Todo
func CreateTodo(todo *Todo) (err error) {err = dao.DB.Create(&todo).Errorreturn
}// GetTodoList 获取全部的Todo
func GetTodoList() (todoList []*Todo, err error) {if err = dao.DB.Find(&todoList).Error; err != nil {return nil, err}return
}// GetTodoById 通过id获取一个Todo对象
func GetTodoById(id string) (todo *Todo, err error) {todo = new(Todo)if err = dao.DB.Where("id=?", id).First(&todo).Error; err != nil {return nil, err}return
}// UpdateTodoById 更新一个Todo对象
func UpdateTodoById(todo *Todo) (err error) {err = dao.DB.Save(todo).Errorreturn
}// DeleteTodo
func DeleteTodo(id string) (err error) {err = dao.DB.Where("id=?", id).Delete(&Todo{}).Errorreturn
}
3.dao
dao:存放关于数据库的相关操作
package daoimport "github.com/jinzhu/gorm"var (DB *gorm.DB
)func InitMySQL() (err error) {DB, err = gorm.Open("mysql", "usr1:12345@tcp(***:3306)/db1?charset=utf8&parseTime=True&loc=Local")if err != nil {panic(err)}return DB.DB().Ping()
}
4.router
router:一般用于设置路由
package routerimport ("gin_demo_BubbleList/controller""github.com/gin-gonic/gin"
)func SetRouter() *gin.Engine {r := gin.Default()//设置静态资源文件r.Static("/static", "static")// 设置gin框架模版文件r.LoadHTMLGlob("templates/*")//设置路由r.GET("/", controller.IndexHandler)//设置路由组v1Group := r.Group("/v1"){//添加一个事项v1Group.POST("/todo", controller.Create)//查看所有事项v1Group.GET("/todo/", controller.GetTodoList)//修改一个事项v1Group.PUT("/todo/:id", controller.UpdateById)//删除一个事项v1Group.DELETE("/todo/:id", controller.DeleteById)}return r
}
4.整体架构
我的源码:6月/gin_demo_BubbleList · 沉着冷静/2023 - 码云 - 开源中国 (gitee.com)