基于gin框架和gorm的待办清单小项目 | 青训营

63 阅读5分钟

记录一下暑假的时候学习GORM和GIN框架的时候写的一个增删改查的小项目(todoList)

参考教程:

基于gin框架和gorm的web开发实战

项目目录结构如下:(使用CMD中的tree命令生成)

├─controller
├─dao
├─models
├─static
│  ├─css
│  ├─fonts
│  └─js
└─templates
  • controller:该目录包含了控制器(Controller)的代码,用于处理请求和响应。

  • dao:该目录包含了数据访问对象(DAO)的代码,用于与数据库进行交互。

  • models:该目录包含了模型(Model)的代码,用于定义数据结构和业务逻辑。

  • static:该目录包含了静态资源文件。

  • templates:该目录包含了项目的模板文件。

dao层

package dao  
  `
import (  
"gorm.io/driver/mysql"  
"gorm.io/gorm"  
)  
  
var (  
Db *gorm.DB  
)  
  
func IntMysql() {  
//连接MySql数据库  
dsn := "root:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"  
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})  
//判断是否连接成功   
if err != nil {  
panic(err)  
}  
Db = db  
//变量赋值
}

Db:对外暴露的数据库变量

models层

定义todo的结构体

type Todo struct {  
ID int `json:"id"`  
Title string `json:"title"`  
Status bool `json:"status"`  
}

属性名大写可以使得类型及其属性数据能被公开访问到。

Tag在结构体字段的后方定义,由一对反引号包裹起来

通过指定tag实现json序列化该字段时的key;json序列化是默认使用字段名作为key;私有不能被json包访问

todo模型的增删改查

func CreateTodo(todo *Todo) (err error) {  
    err = dao.Db.Create(&todo).Error  
    if err != nil {  
    return err  
    }  
    return nil  
}  
  
func GetTodoList() (todoList []Todo, err error) {  
    err = dao.Db.Find(&todoList).Error  
    if err != nil {  
    return nil, err  
    }  
    return todoList, nil  
}  
  
func EditTodoById(id string, todo *Todo) (err error) {  
    err = dao.Db.Where("id=?", id).First(&todo).Error  
    if err != nil {  
    return err  
    }  
    return nil  
}  
  
func SaveTodo(todo *Todo) (err error) {  
    err = dao.Db.Save(&todo).Error  
    if err != nil {  
    return err  
    }  
    return nil  
}  
  
func DeleteTodoById(id string) (err error) {  
    err = dao.Db.Delete(&Todo{}, "id=?", id).Error  
    if err != nil {  
    return err  
    }  
    return nil  
}

controller层

处理请求和响应

type Todo struct {  
    ID int `json:"id"`  
    Title string `json:"title"`  
    Status bool `json:"status"`  
}

func AddTodo(c *gin.Context) {  
    var todo Todo  
    //将请求中的数据绑定到todo中,并判断是否绑定成功  
    err := c.BindJSON(&todo)  
    //判断数据是否为空  
    if todo.Title == "" {  
    c.JSON(http.StatusBadRequest, gin.H{"error": "title不能为空"})  
    return  
    }  
    if err != nil {  
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})  
    return  
    } else {  
    //将todo存入数据库  
    err := models.CreateTodo((*models.Todo)(&todo))  
    if err != nil {  
    return  
    }  
    //返回数据  
    c.JSON(http.StatusOK, todo)  
    }  
}  
  
func GetTodoList(c *gin.Context) {  
    todoList, err := models.GetTodoList()  
    if err != nil {  
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})  
    return  
    } else {  
    c.JSON(http.StatusOK, todoList)  
    }  
}  
  
func EditTodo(c *gin.Context) {  
    id := c.Params.ByName("id")  
    var todo Todo  
    if err := models.EditTodoById(id, (*models.Todo)(&todo)); err != nil {  
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})  
    return  
    }  
    if err := c.BindJSON(&todo); err != nil {  
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})  
    return  
    }  
    if err := models.SaveTodo((*models.Todo)(&todo)); err != nil {  
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})  
    return  
    }  
    c.JSON(http.StatusOK, todo)  
}  
  
func DeleteTodo(c *gin.Context) {  
    id := c.Params.ByName("id")  
    if id == "" {  
    c.JSON(http.StatusBadRequest, gin.H{"error": "id不能为空"})  
    return  
    }  
    if err := models.DeleteTodoById(id); err != nil {  
    c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})  
    return  
    }  
    c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "success"})  
}

基于Gin框架的API接口实现。

  1. AddTodo函数用于添加一个新的待办事项。首先,它将请求中的JSON数据绑定到一个Todo结构体中,并检查是否绑定成功。然后检查待办事项的标题是否为空,将todo存入数据库中,并返回给客户端。
  2. GetTodoList函数用于获取待办事项列表:调用models包中的GetTodoList函数从数据库中获取所有待办事项,并将它们作为JSON数据返回给客户端。
  3. EditTodo函数用于编辑一个待办事项:从URL参数中获取todo的id。然后,它调用models包中的EditTodoById函数,将指定id的待办事项的内容复制到一个Todo结构体中。接着将请求中的JSON数据绑定到该Todo结构体中,并检查是否绑定成功。最后调用models包中的SaveTodo函数将修改后的待办事项保存到数据库中,并返回给客户端。
  4. DeleteTodo函数用于删除一个待办事项:从URL参数中获取待办事项的id,并调用models包中的DeleteTodoById函数删除该待办事项。如果删除成功,则返回成功的状态码和消息给客户端。如果删除失败,则返回错误信息给客户端。

main.go

调用dao包中的IntMysql函数来初始化数据库连接

创建一个默认的Gin引擎实例r,设置路由,通过r.GET函数将根路径"/"映射到controller包中的IndexHandler函数

创建一个名为v1的路由组,将所有以"/v1"开头的请求都分发到该路由组中处理

在v1路由组中,创建一个名为todo的子路由组,将所有以"/v1/todo"开头的请求都分发到该子路由组中处理

最后,调用r.Run()函数启动Gin引擎,监听并处理HTTP请求

package main  
  
import (  
"bubble/controller"  
"bubble/dao"  
"bubble/models"  
"github.com/gin-gonic/gin"  
)  

func main() {  
dao.IntMysql()  
//自动迁移
dao.Db.AutoMigrate(&models.Todo{})  
r := gin.Default()  
//引用静态文件  
r.Static("/static", "./static")  
//引用模板文件  
r.LoadHTMLGlob("templates/*")  
//设置路由  
r.GET("/", controller.IndexHandler)  
v1 := r.Group("v1")  
{  
todo := v1.Group("todo")  
//增加某个todo  
todo.POST("", controller.AddTodo)  
//查看全部todo  
todo.GET("", controller.GetTodoList)  
//修改某个todo  
todo.PUT(":id", controller.EditTodo)  
//删除某个todo  
todo.DELETE(":id", controller.DeleteTodo)  
}  
r.Run()  
} 

接口遵循restful api接口规范

RESTful API是一种基于HTTP协议设计的API规范,它的设计原则包括以下几点:

  1. 使用合适的HTTP方法:使用HTTP的GET、POST、PUT、DELETE等方法来表示对资源的不同操作。其中,GET用于获取资源,POST用于创建资源,PUT用于更新资源,DELETE用于删除资源。
  2. 使用合适的URL结构:URL应该具有清晰的结构,能够表达资源的层级关系。例如,使用"/users"表示用户资源,使用"/users/{id}"表示特定用户的资源。
  3. 使用合适的HTTP状态码:使用合适的HTTP状态码来表示请求的处理结果。例如,200表示成功,201表示创建成功,400表示请求错误,404表示资源不存在,500表示服务器错误等。
  4. 使用合适的HTTP头部:使用合适的HTTP头部来传递额外的信息。例如,使用"Content-Type"头部来指定请求或响应的数据格式,使用"Authorization"头部来进行身份验证等。
  5. 使用合适的请求和响应格式:使用合适的数据格式来进行请求和响应的数据传输。常用的数据格式包括JSON、XML等。
  6. 使用合适的错误处理机制:对于错误的处理,应该使用合适的错误码和错误信息来返回给客户端。同时,应该提供详细的错误信息,方便客户端进行问题排查。
  7. 使用合适的版本控制:对于API的变更,应该使用合适的版本控制机制,以兼容旧版本的客户端。