当前位置: 首页 > news >正文

【Go】-基于Gin和GORM的小清单项目

目录

项目介绍

简介

技术

项目结构

项目分析

总结 


项目介绍

简介

        项目地址:knoci/list: 基于Gin的待办清单小项目 (github.com)

        一个仿照github/Q1mi/bubble 做的一个gin框架练习

技术

  • gin 框架
  • gorm 操作PostgreSQL
  • ini 配置文件

项目结构

list
├── README.md
├── config
│   └── config.ini
├── controller
│   └── controller.go
├── dao
│   └── postgresql.go
├── go.mod
├── go.sum
├── main.go
├── models
│   └── todo.go
├── routers
│   └── routers.go
├── 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
└── templates├── favicon.ico└── index.html

项目分析

        项目中有config,controllers,dao,models,routers,static,template这7个文件夹。

  • config保存ini文件,配置连接数据库的参数(Port,User,Password...)
  • controllers保存控制函数,实现器功能,处理web响应
  • dao连接数据库
  • models是各种数据结构模板定义
  • routers负责路由分组和路由处理
  • static存储静态资源
  • template是前端模板

        接下来我们从mian.go开始,逐步分析整个项目的运行。

package mainimport ("list/dao""list/models""list/routers"//_ "gorm.io/driver/mysql"_ "gorm.io/driver/postgres"
)func main() {//连接数据库dao.Connect()//模型绑定dao.DB.AutoMigrate(&models.Todo{})//启动routerrouters.SetupRouter()
}

        在main.go中我们导入了同文件夹下的dao,models,routers;随后运行第一个函数 dao.Connect(),接下来我们进入dao,来看看 dao.Connect() 函数实现了什么功能

package daoimport ("fmt""gopkg.in/ini.v1"//"gorm.io/driver/mysql""gorm.io/driver/postgres""gorm.io/gorm"
)var (DB *gorm.DB
)type MysqlConfig struct {User     string `ini:"user"`Password string `ini:"password"`Host     string `ini:"host"`Port     string `ini:"port"`DBname   string `ini:"db"`
}func LoadConfig() *MysqlConfig {//development_通过结构体映射参数c := new(MysqlConfig)ini.MapTo(c, "config/config.ini")fmt.Println(c)return c
}func Connect() {c := LoadConfig()dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s", c.Host, c.User, c.Password, c.DBname, c.Port)/* mysqldsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",c.User, c.Password, c.Host, c.Port, c.DBname)dsn := "root:root1234@tcp(127.0.0.1:13306)/bubble?charset=utf8mb4&parseTime=True&loc=Local"*/var err errorDB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{}) // connect// mysql DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})if err != nil {panic(err.Error())}fmt.Print("==========连接数据库成功==========\n")
}

        在postgresql.go中导入了GORM,PG驱动,ini包,自定义了结构体Mysqlconfig,和一个 导包全局可访问的 gorm.DB类型的指针DB,封装了一个函数 LoadConfig() 通过ini.MapTo(c, "config/config.ini") 来接收配置文件。

        在Connect函数中调用LoadConfig()获得配置,用Sprintf()把配置复制到dsn,然后通过gorm.Open方法连接到我们的数据库。

        dao.Connect()完成后,我们继续回到main.go,用dao包内变量DB的内置方法 dao.DB.AutoMigrate(&models.Todo{}) ,实现了模型绑定,实际上就是按照models.Todo结构体在数据库中创建了一张表。

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

        Todo表中,每个待办事项有ID,Title,Status,并且有相应JOSN的tag。其中ID是用来标识事项的自增唯一值,Title是事务名,Status用0和1表示未完成和完成。

        回到main.go,最后调用了routers.SetupRouter(),这是在本地routers包routers.go里的函数。在SetupRouter中,使用gin.Default()注册默认路由r;然后用r.Static()导入./static目录下静态文件指定为static;接着用r.LoadHTMLGlob()导入当前路径template/*的模板。

        接着就是路由处理,指定了对"/"的GET请求回应controllers.ShowIndex函数,用r.Group()定义了路由组v1Group。

        路由组中,指定了对"todo"的POST请求回应controllers.CreateTodo函数,对"/todo"的GET请求回应controllers.RetrieveTodo函数,对"/todo/:id"的PUT请求回应controllers.UpdateTodo函数,对"/todo/:id"的DELETE请求回应controllers.DeleteTodo函数。

        最后用r.Run(:9090),在9090端口上监听并运行。

package routersimport ("github.com/gin-gonic/gin""list/controllers"
)func SetupRouter() {r := gin.Default()r.Static("/static", "static")r.LoadHTMLGlob("template/*")r.GET("/", controllers.ShowIndex)v1Group := r.Group("v1"){//添加v1Group.POST("todo", controllers.CreateTodo)//查看v1Group.GET("/todo", controllers.RetrieveTodo)//修改v1Group.PUT("/todo/:id", controllers.UpdateTodo)//删除v1Group.DELETE("/todo/:id", controllers.DeleteTodo)}r.Run(":9090")}

        接下来看看controller中的各个函数的功能,首先是ShowIndex,负责返回状态码200,展示index.html。

func ShowIndex(c *gin.Context) {c.HTML(http.StatusOK, "index.html", nil)
}

        CreateTodo 用来创建一个待办事项。在接收到传来的数据后,定义一个models.Todo类型的todo结构体,然后用 c.ShouldBind(&todo) 自动的进行响应格式(这里是JSON)的参数绑定到todo,然后通过 dao.DB.Create(&todo) 把todo存入数据库DB,以JSON格式失败返回报错,成功返回todo。

func CreateTodo(c *gin.Context) {//get datavar todo models.Todoc.ShouldBind(&todo)//add into databaseerr := dao.DB.Create(&todo).Error//returnif err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return} else {c.JSON(http.StatusOK, todo)}}

        RetrieveTodo 用来获取所有待办事项,创建一个结构体数组todos,用 dao.DB.Find(&todos) 把所有的表数据给到todos,以JSON格式失败返回报错,成功返回todos。

func RetrieveTodo(c *gin.Context) {var todos []models.Todoif err := dao.DB.Find(&todos).Error; err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error()})return} else {c.JSON(http.StatusOK, todos)}
}

         UpdateTodo 用来更新指定的事项,用 c.Params.GET("id") 获得要修改事项名为"id"的指定url,定义todo结构体然后用 dao.DB.Where("id=?", id).First(&todo) 来查询数据库中第一个对应id的数据到todo,然后 c.BindJSON(&todo) 把方法请求体c以JSON绑定到todo,最后 dao.DB.Save(&todo) 来更新数据库。

func UpdateTodo(c *gin.Context) {id, ok := c.Params.Get("id")if !ok {c.JSON(http.StatusOK, gin.H{"error": "id invalid"})return}var todo models.Todoif err := dao.DB.Where("id=?", id).First(&todo).Error; err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error()})return}c.BindJSON(&todo) //修改if err := dao.DB.Save(&todo).Error; err != nil {c.JSON(http.StatusOK, gin.H{"error": err.Error()})} else {c.JSON(http.StatusOK, todo)}
}

        DeletTodo 用来删除一个待办事项,还是通过 c.Params.GET("id") 获得要修改事项名为"id"的指定url,用 dao.DB.Where("id=?", id).Delete(models.Todo{}) 来删除数据库中对应id的数据,因为这里不接收请求体,没有定义局部变量结构体,所以直接传入model.Todo{}指定表格式。


总结 

        这个项目是Gin和GORM的非常非常简单的小项目,适合新手入门。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • PPStructure核心源码研究(三)LayoutPredictor类详解
  • 昇思MindSpore AI框架MindFormers实践3:ChatGLM3-6B对一段文字进行提取
  • Qt 边框border - qss样式
  • 如何从github上clone项目
  • 品牌借势华为三折叠手机上市热点文案
  • 基于Java+Mysql实现(web)大型企业管理系统
  • 大数据Flink(一百一十八):SQL水印操作(Watermark)
  • 项目实战 (11)---搜索进度
  • 人工智能辅助汽车造型设计
  • 第307题|快速掌握 反常积分敛散性判定的方法|武忠祥老师每日一题
  • 基于k8s手动部署rabbitmq集群(Manually Deploying RabbitMQ Cluster Based on k8s)
  • Spring Cloud集成Gateaway
  • 【视频教程】基于python深度学习遥感影像地物分类与目标识别、分割实践技术应用
  • Linux shell编程学习笔记80:gzip命令——让文件瘦身
  • redis底层—数据结构
  • JavaScript 如何正确处理 Unicode 编码问题!
  • 「面试题」如何实现一个圣杯布局?
  • 2017 年终总结 —— 在路上
  • C++类中的特殊成员函数
  • Js基础知识(一) - 变量
  • Unix命令
  • 产品三维模型在线预览
  • 读懂package.json -- 依赖管理
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 讲清楚之javascript作用域
  • 漂亮刷新控件-iOS
  • 全栈开发——Linux
  • 如何实现 font-size 的响应式
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 原生js练习题---第五课
  • AI算硅基生命吗,为什么?
  • ​插件化DPI在商用WIFI中的价值
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • #[Composer学习笔记]Part1:安装composer并通过composer创建一个项目
  • (1)(1.9) MSP (version 4.2)
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (6)STL算法之转换
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (一)认识微服务
  • (转)fock函数详解
  • ... 是什么 ?... 有什么用处?
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .NET Core6.0 MVC+layui+SqlSugar 简单增删改查
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • /etc/motd and /etc/issue
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • @AliasFor注解
  • [Algorithm][综合训练][体育课测验(二)][合唱队形][宵暗的妖怪]详细讲解
  • [ANT] 项目中应用ANT
  • [BUG]vscode插件live server无法自动打开浏览器
  • [cogs2652]秘术「天文密葬法」