【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的非常非常简单的小项目,适合新手入门。
相关文章:
【Go】-基于Gin和GORM的小清单项目
目录 项目介绍 简介 技术 项目结构 项目分析 总结 项目介绍 简介 项目地址:knoci/list: 基于Gin的待办清单小项目 (github.com) 一个仿照github/Q1mi/bubble 做的一个gin框架练习 技术 gin 框架gorm 操作PostgreSQLini 配置文件 项目结构 list ├── R…...
【银河麒麟高级服务器操作系统】虚拟机服务器执行systemctl提示timeout——分析全过程及处理建议
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://documentkylinos.cn 现象描述 产品信息 产品名称 银河麒麟高级服务…...
【Unity错误】No cloud project ID was found by the Analytics SDK
在编译默认的URP 2D项目时,出现这样一个错误:No cloud project ID was found by the Analytics SDK. This means Analytics events will not be sent. Please make sure to link your cloud project in the Unity editor to fix this problem. 原因&…...
2. 变量和指令(omron 机器自动化控制器)——1
机器自动化控制器——第二章 变量和指令 1 2-1 变量一览表MC通用变量轴变量▶ 轴组变量 运动控制指令的输入变量输入变量的有效范围▶ 枚举体一览表 运动控制指令的输出变量运动控制指令的输入输出变量 2-1 变量一览表 MC功能模块使用的变量分为两类。 一类是监视轴等的状态及…...
gpt4最新保姆级教程
如何使用 WildCard 服务注册 Claude3 随着 Claude3 的震撼发布,最强 AI 模型的桂冠已不再由 GPT-4 独揽。Claude3 推出了三个备受瞩目的模型:Claude 3 Haiku、Claude 3 Sonnet 以及 Claude 3 Opus,每个模型都展现了卓越的性能与特色。其中&a…...
Java:继承和多态(1)
在 Java SE 中,继承和多态是面向对象编程(OOP)的两个核心概念。通过继承,子类可以复用父类的代码;而通过多态,子类可以在不修改父类的前提下定义自己的行为。这两者结合起来使得代码更具扩展性、灵活性和可…...
在RabbitMQ中四种常见的消息路由模式
1. Fanout模式 Fanout模式的交换机是扇出交换机(Fanout Exchange),它会将消息广播给所有绑定到它的队列,而不考虑消息的内容或路由键。 工作原理: 生产者发送消息到Fanout Exchange。Fanout Exchange会将消息广播给…...
Android 使用JSON动画:Lottie框架基本使用
Lottie是什么? GitHub的一种跨平台动画解决方案三方框架 使用? 3步 1.引入最新的依赖:https://github.com/airbnb/lottie-android 我写文章时最新版本是6.5.2 添加到 app/build.gradle 文件的以下方法中dependencies {//lottie 动画implementation com.airbnb.android:l…...
【SQL】百题计划 - SQL最基本的判断和查询。
[SQL]百题计划 Select product_id from Products where low_fats "Y" and recyclable "Y";...
C++学习笔记----6、内存管理(五)---- 智能指针(2)
书接上回! make_unique()使用值初始化。例如,将初始类型初始化为0,对象为缺省构造。如果不需要这样的值初始化,例如,因为不管怎么样你都会覆写共初始值,你就可以省略值初始化,通过使用make_uniq…...
游戏出海迎新变局——海外游戏市场有哪些新趋势和新机遇?
游戏出海的热度越来越高,也面临着竞争加剧、门槛提升、成本增加的现实环境,游戏出海有哪些新变化和新趋势? 移动游戏出海的主要海外市场 在海外市场分布方面,美日韩仍然是我国移动游戏重要的海外市场,占据了中国出海…...
【Unity踩坑】创建新项目后提示编译错误要进入安全模式
在创建了新项目后(比如URP,AR,VR),首次打开时提示有编译错误,要进入安全模式。 脚本是项目模板自带的,不会有问题。这时需要先选择进入安全模式,然后关闭项目,重新打开就…...
SpringBoot开发——整合Logbook进行HTTP API请求响应日志输出
文章目录 1. 简介依赖管理2. 实战案例2.1 基本用法2.2 结合Logback日志记录到文件2.3 自定义核心类Logbook2.4 自定义日志输出Sink2.5 与RestTemplate集成1. 简介 记录HTTP API请求响应日志对于监控、调试和性能优化至关重要。它帮助开发者追踪API的使用情况,包括请求来源、参…...
【嵌入式开发 Linux 常用命令系列 7.1 -- git log 只显示日期和主题(title)和commit id】
文章目录 git log 只显示日期和主题(title)和commit id示例其他日期格式选项 git log 只显示日期和主题(title)和commit id 要使用 git log 仅显示提交的日期、提交消息(title)和提交号(commit hash),你可以使用自定义…...
Android Radio2.0——交通公告状态设置(二)
通过前面的学习,我们知道在 Radio 广播中,交通公告(Traffic Announcement, TA)是一个比较重要的概念,它和交通广播(Traffic Radio)是相关的概念,但它们并不完全相同。 一、简介 1、概念介绍 交通公告 定义:交通公告是指在广播中插入的特别信息,通常是关于交通状况…...
用centos安装远程迅雷失败,重写程序做一台下载服务器
安装远程迅雷的时候,要不是安装包地址过期,就是出现64不兼容32的libz.so.1的包,而且32位的libz包也是好多网站过期。 没办法用仅有的python3,用flask搭建了一个小型的内网下载服务器,当然,只要路由器做映射…...
Mysql基础练习题 1407.排名靠前的旅行者(力扣)
编写解决方案,报告每个用户的旅行距离。 # 返回的结果表单,以 travelled_distance 降序排列 ,如果有两个或者更多的用户旅行了相同的距离, 那么再以 name 升序排列 。 题目链接: https://leetcode.cn/problems/top-travellers/d…...
一维稳态与非稳态导热的详细分析
目录 引言 一维稳态导热 应用实例:单层平壁导热 数值求解: 一维非稳态导热 应用实例:单层平壁的非稳态导热 温度变化阶段 表格总结: 引言 热传导(Heat Conduction)是热量在物体内部通过微观粒子的相…...
以太坊开发环境
1. 测试网络 可以使用以下命令将以太坊的 Go 语言客户端 Geth 连接到测试网络 [admindaolian ~]$geth --testnet 下图显示了示例输出,该图显示了所选网络的类型以及有关区块链下载的其他各种信息。 Geth 客户端的下载地址如下: https://geth.ethereum…...
深入理解Java虚拟机:Jvm总结-虚拟机字节码执行引擎
第八章 虚拟机字节码执行引擎 8.1 意义 不受物理条件制约地定制指令集与执行引擎的结构体系,能够执行那些不被硬件直接支持的指令集格式。输入的是字节码二进制流,处理过程是字节码解析执行的等效过程,输出的是执行结果 8.2 运行时栈帧结构…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
