todo 小清单:gin + gorm 实战学习
说明
基于 gin
+ gorm
源项目仓库地址:Q1mi - bubble
仓库地址:xxcheng - todo
目录结构
|-- conf 配置文件
| |-- config.go
| |-- config.ini
| `-- config.ini.example
|-- controller 控制
| `-- controller.go
|-- dao 接口
| `-- mysql.go
|-- go.mod
|-- go.sum
|-- main.go 入口
|-- models 模型
| `-- todo.go
|-- readme.md
|-- routers 路由
| `-- routers.go
|-- static 静态资源
| |-- css
| |-- fonts
| `-- js
`-- templates HTML模板
|-- favicon.ico
`-- index.html
准备工作
创建数据库
CREATE DATABASE go_todo;
安装依赖
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
go get -u gopkg.in/ini.v1
步骤拆分
持久化处理
dao/mysql.go
package dao
// ...
var (
DB *gorm.DB
)
func InitMySQL(cfg *conf.MySQLConfig) (err error) {
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
cfg.User,
cfg.Password,
cfg.Host,
cfg.Port,
cfg.DatabaseName,
)
DB, err = gorm.Open(mysql.Open(dsn))
if err == nil {
return
}
return err
}
实体封装
ORM
模型
models/todo.go
type Todo struct {
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
ID uint `json:"id" gorm:"primarykey"`
Title string `json:"title"`
Status bool `json:"status"`
}
操作
models/todo.go
package models
// 添加
func AddTodo(todo *Todo) (err error) {
return dao.DB.Create(&todo).Error
}
// 修改
func ModifyTodo(todo *Todo) (err error) {
return dao.DB.Save(&todo).Error
}
// 删除
func DeleteTodo(ID string) (err error) {
return dao.DB.Delete(&Todo{}, ID).Error
}
// 查询所有
func GetAllTodos() (todos []*Todo, err error) {
err = dao.DB.Find(&todos).Error
return todos, err
}
// 查询
func GetTodo(ID string) (todo *Todo, err error) {
todo = new(Todo)
err = dao.DB.First(&todo, ID).Error
return todo, err
}
控制交互
controller/controller.go
package controller
type Todo = models.Todo
// 首页请求
func IndexHandle(ctx *gin.Context) {
ctx.HTML(200, "index.html", nil)
}
// 增加 请求
func AddTodo(ctx *gin.Context) {
var todo Todo
ctx.BindJSON(&todo)
if err := models.AddTodo(&todo); err != nil {
ctx.JSON(200, gin.H{
"code": 1,
"message": err,
})
} else {
ctx.JSON(200, gin.H{
"code": 0,
"message": "success",
"data": &todo,
})
}
}
//更新 请求
func UpdateTodo(ctx *gin.Context) {
ID, isExist := ctx.Params.Get("id")
if !isExist {
ctx.JSON(200, gin.H{
"code": 1,
"message": "id字段未提供~",
})
return
}
todo, err := models.GetTodo(ID)
if err != nil {
ctx.JSON(200, gin.H{
"code": 1,
"message": err,
})
return
}
ctx.BindJSON(&todo)
err = models.ModifyTodo(todo)
if err != nil {
ctx.JSON(200, gin.H{
"code": 1,
"message": err,
})
return
}
ctx.JSON(200, gin.H{
"code": 0,
"data": todo,
})
}
// 删除 请求
func DeleteTodo(ctx *gin.Context) {
ID, isExist := ctx.Params.Get("id")
if !isExist {
ctx.JSON(200, gin.H{
"code": 1,
"message": "id字段未提供~",
})
return
}
err := models.DeleteTodo(ID)
if err != nil {
ctx.JSON(200, gin.H{
"code": 1,
"message": err,
})
return
}
ctx.JSON(200, gin.H{
"code": 0,
})
}
// 获取所有记录 请求
func GetAllTodos(ctx *gin.Context) {
if todos, err := models.GetAllTodos(); err != nil {
ctx.JSON(200, gin.H{
"code": 1,
"message": err,
})
} else {
ctx.JSON(200, todos)
}
}
路由处理
加载模板、加载静态资源、路由注册
routers/routers.go
package routers
func SetupRputer() *gin.Engine {
r := gin.Default()
//加载模板
r.LoadHTMLGlob("templates/*")
//加载静态资源
r.Static("/static", "static")
r.GET("/", controller.IndexHandle)
v1Group := r.Group("/v1")
{
//提交新的
v1Group.POST("/todo", controller.AddTodo)
//获取全部
v1Group.GET("/todo", controller.GetAllTodos)
//更新
v1Group.PUT("/todo/:id", controller.UpdateTodo)
//删除
v1Group.DELETE("/todo/:id", controller.DeleteTodo)
}
return r
}
其他
配置模板
conf/config.go
package conf
var Conf = new(ApplicationConfig)
type ApplicationConfig struct {
Port uint16 `ini:"port"`
*MySQLConfig `ini:"mysql"`
}
type MySQLConfig struct {
User string `ini:"user"`
Password string `ini:"password"`
Host string `ini:"host"`
Port uint16 `ini:"port"`
DatabaseName string `ini:"dbName"`
}
func Init(file string) error {
return ini.MapTo(Conf, file)
}
配置文件
config/config.ini
port=19999
[mysql]
user=root
password=jpc0519Qcloud
host=host
port=port
dbName=dbName
入口 & 启动
main.go
const defaultConfFile = "./conf/config.ini"
func main() {
conf.Init(defaultConfFile)
//连接数据库
dao.InitMySQL(conf.Conf.MySQLConfig)
//绑定模型
r := routers.SetupRputer()
dao.DB.AutoMigrate(&models.Todo{})
r.Run(fmt.Sprintf(":%d", conf.Conf.Port))
}
运行效果
首次访问
添加数据
更新状态
删除
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。