【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 main

import (
	"list/dao"
	"list/models"
	"list/routers"

	//_ "gorm.io/driver/mysql"
	_ "gorm.io/driver/postgres"
)

func main() {
	//连接数据库
	dao.Connect()
	//模型绑定
	dao.DB.AutoMigrate(&models.Todo{})
	//启动router
	routers.SetupRouter()
}

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

package dao

import (
	"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)
	/* mysql
	dsn := 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 error
	DB, 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 models


type 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 routers

import (
	"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 data
	var todo models.Todo
	c.ShouldBind(&todo)

	//add into database
	err := dao.DB.Create(&todo).Error

	//return
	if 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.Todo
	if 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.Todo
	if 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的非常非常简单的小项目,适合新手入门。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/875499.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

苏茵茵:以时尚之名,诠释品质生活

在女性追求个性化与自我表达的今天,时尚早已超越了简单的穿着打扮,它成为女性展现自我风格、彰显独特魅力的重要方式。从广泛的兴趣爱好到精心雕琢的个人风格,每一处细节都闪耀着女性对个性独特与自我表达的深切渴望。正是这股不可阻挡的潮流…

Unity6 + UE5.4 PSO缓存实践记录

题图(取自COD冷战的着色器编译提示) PSO(管线状态对象 Pipeline State Object)是伴随现代图形API(DirectX12、Vulkan、Metal)而出现的概念,它本质上是单次绘制时渲染管线所处的状态信息的集合&…

Blender渲染太慢怎么办?blender云渲染已开启

动画行业蓬勃发展,动画制作软件亦持续推陈出新,当制作平台日益丰富,创作难度降低,创作效率提升,如何高效完成复杂动画的渲染就成了从业者更关心的问题。 云渲染技术的出现,无疑为动画制作者提供了前所未有…

kafka原理剖析及实战演练

一、消息系统概述 一)消息系统按消息发送模型分类 1、peer-to-peer(单播) 特点: 一般基于pull或polling接收消息发送对队列中的消息被一个而且仅仅一个接收者所接收,即使有多个接收者在同一队列中侦听同一消息即支持异…

利用熵权法进行数值评分计算——算法过程

1、概述 在软件系统中,研发人员常常遇上需要对系统内的某种行为/模型进行评分的情况。例如根据系统的各种漏洞情况对系统安全性进行评分、根据业务员最近操作系统的情况对业务员工作状态进行打分等等。显然研发人员了解一种或者几种标准评分算法是非常有利于开展研…

中控室控制台处在自动状态什么意思

在现代工业和智能控制系统中,中控室控制台作为集中控制和管理各种设备、系统和流程的核心,扮演着至关重要的角色。当提到中控室控制台处在自动状态时,这通常意味着控制台已经切换到一种高度智能化的工作模式,能够自动调整和管理各…

【SQL】百题计划:SQL判断条件OR的使用。

【SQL】百题计划-20240912 Select name, population, area from World where area>3000000 or population > 25000000;

品读 Java 经典巨著《Effective Java》90条编程法则,第4条:通过私有构造器强化不可实例化的能力

文章目录 【前言】欢迎订阅【品读《Effective Java》】系列专栏java.lang.Math 类的设计经验总结 【前言】欢迎订阅【品读《Effective Java》】系列专栏 《Effective Java》是 Java 开发领域的经典著作,作者 Joshua Bloch 以丰富的经验和深入的知识,全面…

网络运输层之(1)TCP协议基础

网络运输层之(1)TCP协议基础 Author: Once Day Date: 2024年9月12日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可参考专栏: 通信网络技术_Once-Day的博客-…

cv2.bitwise_or 提取ROI区域

原图如下所示,想提取圆形ROI区域,红色框 img np.ones(ori_img.shape, dtype"uint8") img img * 255 cv2.circle(img, (50,50), 50, 0, -1) self.bitwiseOr cv2.bitwise_or(ori_img, circle)使用一个和原图尺寸一致的图像做mask,图白圆黑 以…

通信工程学习:什么是PC永久连接、SPC软永久连接

一、PC永久连接 PC(Permanent Connection)永久连接是一种由网管系统通过网管协议建立的长期稳定的连接方式。在ASON(自动交换光网络)中,PC永久连接沿袭了传统光网络的连接建立形式,其特点主要包括&#xff…

视频监控平台是如何运作的?EasyCVR视频汇聚平台的高效策略与实践

随着科技的飞速发展,视频监控平台在社会安全、企业管理、智慧城市构建等领域发挥着越来越重要的作用。一个高效的视频监控平台,不仅依赖于先进的硬件设备,更离不开强大的视频处理技术作为支撑。这些平台集成了多种先进的视频技术,…

微波无源器件 OMT 2 倍频程带宽紧凑十字转门OMT

摘要: 一个64%瞬态带宽的可变比例十字转门OMT用于在所谓的延伸C频带卫星链接被提出。所体术的结构通过在四个输出矩形波导结处添加一个拓宽的单阶梯来克服现在的实际带宽限制。这个明智的(judicious)调整,和减高度波导和E面弯头的和功率合成器的使用,保证…

kali Linux 安装教程(保姆级)

kali 背景 基于Debian的Linux操作系统 Kali Linux是基于Debian的Linux发行版, 设计用于数字取证操作系统。每一季度更新一次。由Offensive Security Ltd维护和资助。最先由Offensive Security的Mati Aharoni和Devon Kearns通过重写BackTrack来完成,BackT…

专题三_二分查找算法_算法详细总结

目录 二分查找 1.⼆分查找(easy) 1)朴素二分查找,就是设mid(leftright)/2,xnums[mid],t就是我们要找的值 2)二分查找就是要求保证数组有序的前提下才能进行。 3)细节问题: 总结&#xff1a…

系统优化工具 | PC Cleaner v9.7.0.3 绿色版

PC Cleaner是一款功能强大的电脑清理和优化工具,旨在通过清理系统垃圾文件、解除恶意软件和优化系统性能来提高计算机的运行效率。该软件提供了多种功能,可以帮助用户维护和提升计算机的整体表现。 PC Cleaner 支持 Windows 7 及以上操作系统&#xff0…

Visual Studio Installer 2022 安装提示正在提取文件 进度条不动 0B每秒

Visual Studio Installer 稍等片刻...正在提取文件 进度条不动 0B每秒 一段时间后提示 循环下载安装文件 无法下载安装文件。请检查Internet 连接,然后重试 打开vs2017 或者vs2019或者vs2022的安装程序(visual studio installer)时,下载进度条不动&…

智能体 vs AI智能体:区别与联系,一文读懂!

​ 在AI技术蓬勃发展的今天,“智能体”(Agent)和”AI智能体”(AI Agent)两个概念经常被提及,二者在很多场合下会被混淆,但其实它们有着不同的定义和应用。我觉得很有必要小小科普下两者的定义与…

龙芯+FreeRTOS+LVGL实战笔记(新)——06添加二级按钮

本专栏是笔者另一个专栏《龙芯+RT-Thread+LVGL实战笔记》的姊妹篇,主要的区别在于实时操作系统的不同,章节的安排和任务的推进保持一致,并对源码做了完善与优化,各位可以先到本人主页下去浏览另一专栏的博客列表(目前已撰写36篇,图1所示),再决定是否订阅。此外,也可以…

mysql学习教程,从入门到精通,SQL AND OR 运算符(12)

1、SQL AND & OR 运算符 在本教程中,您将学习如何在子句中使用ASELECT column1_name, column2_name, columnN_nameFROM table_nameWHERE condition1 AND condition2;ND&OR运算符,WHERE以根据多个条件过滤记录。 1.1、根据条件选择记录 …