Go 小清单
今天试着复现了一下七米大佬的小清单项目,这里把主要总结一下代码逻辑。
这个项目超级简单,前端代码是已经做好的,直接去大佬仓库clone就行,只不过教程比较久远了,所以代码需要一些调整。
文件结构
代码语言:javascript复制 D:.
│ go.mod
│ go.sum
│ main.go
│
├─.idea
│ .gitignore
│ modules.xml
│ wait.iml
│ workspace.xml
│
├─static
│ ├─css
│ │ app.8eeeaf31.css
│ │ chunk-vendors.57db8905.css
│ │
│ ├─fonts
│ │ element-icons.535877f5.woff
│ │ element-icons.732389de.ttf
│ │
│ └─js
│ app.007f9690.js
│ chunk-vendors.ddcb6f91.js
│
└─template
favicon.ico
index.html
完整代码
代码语言:javascript复制 package main
import (
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"net/http"
)
var db *gorm.DB
// Todo model1
type Todo struct {
ID int `json:"id" gorm:"primaryKey;autoIncrement"`
Title string `json:"title"`
Status bool `json:"status"`
}
func initmysql() {
dsn := "root:root@tcp(127.0.0.1:3306)/bubble?charset=utf8mb4&parseTime=True&loc=Local"
var err error
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect to database: " err.Error())
}
err = db.AutoMigrate(&Todo{})
if err != nil {
panic("failed to migrate database: " err.Error())
}
}
func main() {
// 连接数据库并绑定模型
initmysql()
r := gin.Default()
// 告诉gin框架模板文件引用的静态文件位置
r.Static("/static", "./static")
// 告诉gin框架模板文件的位置
r.LoadHTMLGlob("template/*")
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", nil)
})
v1Group := r.Group("v1")
{
// 添加代办事项
v1Group.POST("/todo", func(c *gin.Context) {
var todo Todo
if err := c.ShouldBindJSON(&todo); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
db.Create(&todo)
c.JSON(http.StatusOK, todo)
})
// 查看特定待办事项
v1Group.GET("/todo/:id", func(c *gin.Context) {
id := c.Param("id")
var todo Todo
if err := db.First(&todo, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Todo not found"})
return
}
c.JSON(http.StatusOK, todo)
})
// 查看所有代办事项
v1Group.GET("/todo", func(c *gin.Context) {
var todos []Todo
db.Find(&todos)
c.JSON(http.StatusOK, todos)
})
// 修改代办事项
v1Group.PUT("/todo/:id", func(c *gin.Context) {
id := c.Param("id")
var todo Todo
if err := db.First(&todo, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Todo not found"})
return
}
if err := c.ShouldBindJSON(&todo); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
db.Save(&todo)
c.JSON(http.StatusOK, todo)
})
// 删除代办事项
v1Group.DELETE("/todo/:id", func(c *gin.Context) {
id := c.Param("id")
if err := db.Delete(&Todo{}, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Todo not found"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Todo deleted"})
})
}
r.Run()
}
全局变量
代码语言:javascript复制 var db *gorm.DB
声明一个全局变量 db
,类型是 *gorm.DB
,用于数据库操作。
Todo 模型
代码语言:javascript复制 type Todo struct {
ID int `json:"id" gorm:"primaryKey;autoIncrement"`
Title string `json:"title"`
Status bool `json:"status"`
}
定义一个 Todo
结构体,用于表示代办事项。包含以下字段:
ID
:主键,自增。Title
:代办事项的标题。Status
:代办事项的状态,表示是否完成。
初始化 MySQL 数据库
代码语言:javascript复制 func initmysql() {
dsn := "root:root@tcp(127.0.0.1:3306)/bubble?charset=utf8mb4&parseTime=True&loc=Local"
var err error
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect to database: " err.Error())
}
err = db.AutoMigrate(&Todo{})
if err != nil {
panic("failed to migrate database: " err.Error())
}
}
- dsn:定义数据库连接字符串,包括用户名、密码、数据库地址、数据库名称和其他参数。
- gorm.Open:使用 GORM 连接到 MySQL 数据库。
- panic:如果连接数据库失败,程序会抛出一个错误并终止运行。
- db.AutoMigrate:自动迁移数据库表结构,确保
Todo
结构体对应的表存在。(数据库中没有对应表的话会新建一个)
主函数
代码语言:javascript复制 func main() {
// 连接数据库并绑定模型
initmysql()
r := gin.Default()
// 告诉gin框架模板文件引用的静态文件位置
r.Static("/static", "./static")
// 告诉gin框架模板文件的位置
r.LoadHTMLGlob("template/*")
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", nil)
})
- initmysql():调用函数连接数据库。
- gin.Default():创建一个默认的 Gin 引擎实例。
- r.Static:设置静态文件的路径。
- r.LoadHTMLGlob:设置模板文件的位置。
- r.GET:定义一个 GET 路由,访问根路径时返回
index.html
模板。
定义 API 路由组
代码语言:javascript复制 v1Group := r.Group("v1")
{
// 添加代办事项
v1Group.POST("/todo", func(c *gin.Context) {
var todo Todo
if err := c.ShouldBindJSON(&todo); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
db.Create(&todo)
c.JSON(http.StatusOK, todo)
})
// 查看特定待办事项
v1Group.GET("/todo/:id", func(c *gin.Context) {
id := c.Param("id")
var todo Todo
if err := db.First(&todo, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Todo not found"})
return
}
c.JSON(http.StatusOK, todo)
})
// 查看所有代办事项
v1Group.GET("/todo", func(c *gin.Context) {
var todos []Todo
db.Find(&todos)
c.JSON(http.StatusOK, todos)
})
// 修改代办事项
v1Group.PUT("/todo/:id", func(c *gin.Context) {
id := c.Param("id")
var todo Todo
if err := db.First(&todo, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Todo not found"})
return
}
if err := c.ShouldBindJSON(&todo); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
db.Save(&todo)
c.JSON(http.StatusOK, todo)
})
// 删除代办事项
v1Group.DELETE("/todo/:id", func(c *gin.Context) {
id := c.Param("id")
if err := db.Delete(&Todo{}, id).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Todo not found"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Todo deleted"})
})
}
r.Run()
}
- r.Group("v1"):创建一个路由组
v1
,用于版本控制。 - POST /todo:添加一个代办事项。通过
ShouldBindJSON
绑定 JSON 数据到Todo
结构体,并保存到数据库。 - GET /todo/ :查看特定的代办事项。通过 URL 参数获取代办事项的 ID 并从数据库查询。
- GET /todo:查看所有代办事项。从数据库中获取所有
Todo
记录。 - PUT /todo/ :修改一个代办事项。通过 URL 参数获取代办事项的 ID 并更新对应的记录。
- DELETE /todo/ :删除一个代办事项。通过 URL 参数获取代办事项的 ID 并从数据库删除。
总结
这段代码实现了一个简单的代办事项(Todo)管理系统,包含以下功能:
- 创建代办事项
- 查看特定代办事项
- 查看所有代办事项
- 修改代办事项
- 删除代办事项
使用 Gin 框架处理 HTTP 请求,使用 GORM 处理 MySQL 数据库操作。
整个代码逻辑并不复杂,只是时间过的比较久了,gorm的对应命令进行一些调整,所以代码也需要进行对应的改动。
参考
https://www.bilibili.com/video/BV1gJ411p7xC/?spm_id_from=333.337.search-card.all.click&vd_source=59fd7d01b725c7ff09c3a0e6221d9016