gorm/gin框架实战
项目简介
学习源视频:【最新Go Web开发教程】基于gin框架和gorm的web开发实战 (七米出品)_哔哩哔哩_bilibili
本博客为我的学习笔记。
项目目标:实现一个备忘录工具(当然不支持alert),仅仅是可以记录待办事项。
实现了:添加待办项、删除待办项、完成待办项、查询待办项
项目主页展示:
添加、查询待办项展示:
删除待办项展示:
项目框架
可以看看之前同专栏的博客,这是一个很基本的框架
package main
import (
"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 Todo
c.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 []Todo
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)
}
})
修改一个事项
//修改一个事项
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{
"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 controller
import (
"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.Todo
c.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 models
import (
"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).Error
return
}
// 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).Error
return
}
// DeleteTodo
func DeleteTodo(id string) (err error) {
err = dao.DB.Where("id=?", id).Delete(&Todo{}).Error
return
}
3.dao
dao:存放关于数据库的相关操作
package dao
import "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 router
import (
"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)