Gin框架简易搭建(3)--Grom与数据库

news2024/12/23 13:02:28

写在前面

项目地址

个人认为GORM 指南这个网站是相比较之下最为清晰的框架介绍

但是它在环境搭建阶段对于初学者而言不是很友好,尤其是使用mysql指令稍有不同,以及更新的方法和依赖问题都是很让人头疼的,而且这些报错并非逻辑上的,往往是网络端口,数据库创建等没有接触过的内容,因此我建议可以在学习使用增删改查的操作时看框架教程,配置环境使用以下的学习步骤:

  1. 首先,下载mysql,以及三选一mysqlshell,navicat,dbreaver(个人感觉第二个的破解版手感是最丝滑的),对于初学一个东西,我认为可视化是最好的帮助和激励

  2. 在创建和连接数据库的时候,搜一下“Navicat使用快速入门教程”,对于数据库连接不成功的情况,往往是因为没有启动服务,这个在任务管理器->服务->mysql90(或80),找到之后右键手动打开即可,简单学一下建表(增删改查都看一下也可以,大概十几分钟就搞定)

  3. 之后,使用下面两个命令在项目中搭建gorm环境

    go get -u gorm.io/gorm
    go get -u gorm.io/driver/mysql
    
  4. 然后,按照下面的文件结构去添加文件夹和文件即可,由于版本的原因,我直接上传所有新增文件,并且以注释的形式去解释每部分的作用

    在这里插入图片描述

文件及解析

dao.go

package dao

import (
	"Ranking/config"
	"Ranking/pkg/logger"
	"gorm.io/driver/mysql" // 引入 MySQL 驱动
	"gorm.io/gorm"         // 引入 Gorm
	"time"
)

var (
	Db  *gorm.DB
	err error
)

func init() {
	// 使用 gorm.Open 打开 MySQL 数据库连接
	Db, err = gorm.Open(mysql.Open(config.Mysqldb), &gorm.Config{})
	if err != nil {
		logger.Error(map[string]interface{}{"mysql connect error": err.Error()})
		return // 连接失败,提前返回
	}

	// 获取底层的 sql.DB
	sqlDB, err := Db.DB()
	if err != nil {
		logger.Error(map[string]interface{}{"get DB instance error": err.Error()})
		return // 获取 DB 实例失败,提前返回
	}

	// 配置连接池参数
	sqlDB.SetMaxIdleConns(10)           // 设置最大空闲连接数
	sqlDB.SetMaxOpenConns(100)          // 设置最大打开连接数
	sqlDB.SetConnMaxLifetime(time.Hour) // 设置连接的最大可重用时长
}

models包user.go

package models

import "Ranking/dao"

type User struct {
	Id       int
	Username string
}

func (User) TableName() string {
	return "user"
}

// GetUsersTest 根据用户ID获取用户信息
func GetUsersTest(id int) (User, error) {
	var user User
	//where在 SQL 中生成一个 WHERE 子句,以便查找满足条件的记录,?是占位符
	//first方法用于查找单个记录,如果找到,则返回该记录,否则返回错误
	err := dao.Db.Where("id =?", id).First(&user).Error
	return user, err
}

controllers->user.go重写一个方法

func (u UserController) GetUserInfo(c *gin.Context) {
	idStr := c.Param("id")
	name := c.Param("name")

	id, _ := strconv.Atoi(idStr)
	user, _ := models.GetUsersTest(id)

	ReturnSuccess(c, 0, name, user, 1)

}

路由(调用getuserinfo,需要传入id)

user.GET("/info/:id", controllers.UserController{}.GetUserInfo)

最需要注意的就是db文件的配置

运行检查:

数据库构建:

在这里插入图片描述

id是创建的数据库里面的id键值(主键)

在这里插入图片描述

增删改查的实现

实现思路:

router.go创建路由
控制user.go创建函数
模块user.go创建方法

代码

可以参考项目地址

router.go

package router

import (
	"Ranking/controllers"
	"Ranking/pkg/logger"
	"github.com/gin-gonic/gin"
	"net/http"
)

// 路由 函数的名字要大写,这样才可以被其他包访问!
func Router() *gin.Engine {
	//创建一个路由的实例
	r := gin.Default()

	//日志
	r.Use(gin.LoggerWithConfig(logger.LoggerToFile()))
	r.Use(logger.Recover)

	//实现GET路由 获取
	r.GET("/hello", func(ctx *gin.Context) {
		ctx.String(http.StatusOK, "hello world")
	})

	//创建这样一个组,简化代码
	user := r.Group("/user")
	{
		//查询单条数据
		user.GET("/info/:id", controllers.UserController{}.GetUserInfo)
		//查询列表数据
		user.POST("/list", controllers.UserController{}.GetList)
		//添加数据
		user.POST("/add", controllers.UserController{}.AddUser)
		//修改数据
		user.POST("/update", controllers.UserController{}.UpdateUser)
		//删除单个用户的数据
		user.POST("/delete", controllers.UserController{}.DeleteUser)
		//获取用户列表
		user.GET("/info/list", controllers.UserController{}.GetAllUsers)
		user.DELETE("/delete", func(ctx *gin.Context) {
			ctx.String(http.StatusOK, "user delete")
		})
	}

	order := r.Group("/order")
	{
		order.GET("/list", controllers.OrderController{}.GetList)
	}

	return r
}

控制user.go

package controllers

import (
	"Ranking/models"
	"Ranking/pkg/logger"
	"fmt"
	"github.com/gin-gonic/gin"
	"strconv"
)

// 实现关于用户的功能
type UserController struct{}

func (u UserController) GetUserInfo(c *gin.Context) {
	idStr := c.Param("id")
	name := c.Param("name")

	id, _ := strconv.Atoi(idStr)
	user, _ := models.GetUsersTest(id)

	ReturnSuccess(c, 0, name, user, 1)

}

func (u UserController) GetList(c *gin.Context) {

	// 程序员手动设置的日志
	logger.Write("日志信息", "user")

	defer func() {
		if err := recover(); err != nil {
			fmt.Println("捕获异常:", err)
		}
	}()

	num1, num2 := 1, 0
	num3 := num1 / num2
	ReturnUserGetListError(c, 404, num3)
}

func (u UserController) AddUser(c *gin.Context) {
	//logger.Write("日志信息", "user")
	username := c.DefaultPostForm("username", "")

	// 输入检查
	if username == "" {
		ReturnError(c, 400, "用户名不能为空")
		return
	}

	id, err := models.AddUser(username)
	if err != nil {
		ReturnError(c, 400, "用户添加失败"+err.Error()) // 返回具体错误信息
		return
	}
	ReturnSuccess(c, 0, "用户添加成功", id, 1)
}

// 更新用户名
func (u UserController) UpdateUser(c *gin.Context) {
	//获取用户信息
	username := c.DefaultPostForm("username", "")
	idStr := c.DefaultPostForm("id", "")
	id, _ := strconv.Atoi(idStr)

	//调用方法更新数据库中的用户名
	models.UpdateUser(id, username)
	ReturnSuccess(c, 0, "用户更新成功", true, 1)
}

// 删除用户
func (u UserController) DeleteUser(c *gin.Context) {
	//获取id
	idStr := c.DefaultPostForm("id", "")
	id, _ := strconv.Atoi(idStr)

	//调用方法删除数据库中的用户
	err := models.DeleteUser(id)
	if err != nil {
		ReturnError(c, 404, "用户删除失败"+err.Error())
	}
	ReturnSuccess(c, 0, "用户删除成功", true, 1)

}

//func (u UserController) GetAllUsers(c *gin.Context) {
//	users, err := models.GetAllUsers()
//	if err != nil {
//		ReturnError(c, 404, "用户列表获取失败"+err.Error())
//	}
//	ReturnSuccess(c, 0, "用户列表获取成功成功", users, 1)
//}

func (u UserController) GetAllUsers(c *gin.Context) {
	users, err := models.GetAllUsers()
	if err != nil {
		ReturnError(c, 404, "用户列表获取失败: "+err.Error())
		return // 添加 return 结束函数的执行
	}

	// 处理成功的情况,避免重复的“成功”字样
	ReturnSuccess(c, 0, "用户列表获取成功", users, 1)
}

注意,在common.go中有需要新建的返回值方法

模块user.go

package models

import (
	"Ranking/dao"
	"fmt"
)

type User struct {
	Id       int
	Username string
}

func (User) TableName() string {
	return "user"
}

// GetUsersTest 根据用户ID获取用户信息
func GetUsersTest(id int) (User, error) {
	var user User
	//where在 SQL 中生成一个 WHERE 子句,以便查找满足条件的记录,?是占位符
	//first方法用于查找单个记录,如果找到,则返回该记录,否则返回错误
	err := dao.Db.Where("id =?", id).First(&user).Error
	return user, err
}

// 调用该方法,存储一个新用户 返回主键和错误信息(controllers包中调用)
func AddUser(username string) (int, error) {
	user := User{Username: username}
	err := dao.Db.Create(&user).Error
	if err != nil {
		return 0, fmt.Errorf("添加用户时出错:%w", err) // 返回详细错误
	}
	return user.Id, nil
}

func UpdateUser(id int, username string) {
	dao.Db.Model(&User{}).Where("id = ?", id).Update("username", username)
}

// DeleteUser 根据用户ID(主键)删除用户
func DeleteUser(id int) error {
	err := dao.Db.Delete(&User{}, id).Error
	return err
}

//func GetAllUsers() ([]User, error) {
//	var users []User
//	//没存够100号 所以拿这个数来返回整个列表
//	err := dao.Db.Where("id < 100", 100).Find(&users).Error
//	return users, err
//}

func GetAllUsers() ([]User, error) {
	var users []User
	//没存够100号 所以拿这个数来返回整个列表
	err := dao.Db.Where("id < ?", 100).Find(&users).Error
	if err != nil {
		return nil, err
	}
	return users, nil
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux 下的静态库与动态库

目录 一、介绍 1、静态库 2、动态库 二、操作 1、静态库 2、动态库 3、使用库文件 &#xff08;1&#xff09;方法一 &#xff08;2&#xff09;方法二 &#xff08;3&#xff09;方法三 一、介绍 1、静态库 静态链接库实现链接操作的方式很简单&#xff0c;即程序文…

vue启动报错

vue执行npm run dev报错如下 Error: error:0308010C:digital envelope routines::unsupportedat new Hash (node:internal/crypto/hash:69:19)at Object.createHash (node:crypto:133:10)at module.exports (F:\ray\taisheng-erp-frontend-master\node_modules\webpack\lib\ut…

深信服2025届全球校招研发笔试-C卷(AK)

前面14个填空题 T1 已知 子数组 定义为原数组中的一个连续子序列。现给定一个正整数数组 arr&#xff0c;请计算该数组内所有可能的奇数长度子数组的数值之和。 输入描述 输入一个正整数数组arr 输出描述 所有可能的奇数长度子数组的和 示例 1 输入 1,4,2,5,3 输出 58 说明 …

[论文精读]Polarized Graph Neural Networks

论文网址&#xff1a;Polarized Graph Neural Networks | Proceedings of the ACM Web Conference 2022 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于…

Junit 5 - 理解Mockito,提高UT 覆盖率

前言 当我是1个3年初级程序员时&#xff0c; 我被面试者问到1个问题&#xff1a; 如何保证你的开发任务交付质量 当我是1个7年开发组长时&#xff0c; 我被面试者问到另1个问题&#xff1a;如何保证你的团队的代码质量&#xff0c; 减少rework。 又若干年后&#xff0c; 我才…

代码随想录Day 58|拓扑排序、dijkstra算法精讲,题目:软件构建、参加科学大会

提示&#xff1a;DDU&#xff0c;供自己复习使用。欢迎大家前来讨论~ 文章目录 图论part08**拓扑排序精讲**题目&#xff1a;117. 软件构建拓扑排序的背景解题思路&#xff1a;模拟过程 **dijkstra&#xff08;朴素版&#xff09;精讲**题目&#xff1a;47. 参加科学大会解题思…

leetcode每日一题day14(24.9.24)——字符串最多的子序列

思路:对于应该首要和贡献联系起来&#xff0c;对于什么是贡献呢&#xff0c;即在某种情况下&#xff0c;会贡献出多少种&#xff0c;符合要求的结果&#xff0c;此题属于较为基础的&#xff0c;对于text中的一个字符如果是非pattern中的元素&#xff0c;则对结果无任何影响&…

舒舒活动图片 小暑至,暑气湿气缠身怎么办?中医教你消暑宁心,健脾祛湿

小暑标志着酷夏的到来&#xff0c;闷热潮湿的气候令人不适&#xff0c;仿佛暑湿交织笼罩全身。众多友人诉苦不已&#xff0c;此般环境致使心绪不宁、身躯疲惫&#xff0c;失措寻对策。实则无需忧虑&#xff0c;持之以恒地进行消暑养心、健脾除湿&#xff0c;便能安然度夏。 暑气…

Vue 技术入门 day1 模版语法、数据绑定、事件处理、计算属性与监视、class和style绑定、条件渲染v-if/v-show、列表渲染v-for

目录 1.Vue 核心 1.1. Vue 简介 1.1.1 介绍与描述 1.1.2 Vue 的特点 1.2 模板语法 1.2.1 模板的分类 1.2.2 插值语法 1.2.3 指令语法 1.2.4 实例 1.3 数据绑定 1.3.1 单向数据绑定 1.3.2 双向数据绑定 1.3.3 MVVM 模型 1.3.4 data与el的2种写法 1.3.5 实例 1.3.…

【C++前缀和】2731. 移动机器人|1922

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 LeetCode2731. 移动机器人 有一些机器人分布在一条无限长的数轴上&#xff0c;他们初始坐标用一个下标从 0 开始的整数数组 nums 表示。当你给机器人下达命令时&…

manim中实现文字换行和设置字体格式

实现换行 from manim import * class Textline(Scene): def construct(self): self.camera.background_color "#2F4F14" # 创建中心文本 horizontal_line Line(startLEFT * 8, endRIGHT * 8, colorWHITE).shift(3 * UP) stext Text("线性代数", …

0. Pixel3 在Ubuntu22下Android12源码拉取 + 编译

0. Pixel3 在Ubuntu22下Android12源码拉取 编译 原文地址: http://www.androidcrack.com/index.php/archives/3/ 1. 前言 这是一个非常悲伤的故事, 因为一个意外, 不小心把之前镜像的源码搞坏了. 也没做版本管理,恢复不了了. 那么只能说是重新做一次. 再者以前的镜像太老旧…

828华为云征文|部署去中心化网络的 AI 照片管理应用 PhotoPrism

828华为云征文&#xff5c;部署去中心化网络的 AI 照片管理应用 PhotoPrism 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 PhotoPrism3.1 PhotoPrism 介绍3.2 PhotoPrism…

OpenHarmony标准系统上实现对rk系列芯片NPU的支持(驱动移植)

1.将RKNPU驱动移植到Openharmony内核 本文以rk3568为例&#xff0c;将RKNPU驱动移植到Openharmony使用的kernel 5.10中 开发环境 DAYU200 rk3568开发板OpenHarmony 4.1 Release 64位系统 文档约定&#xff1a;4.1r_3568为OpenHarmony标准系统源码根目录 1.0 环境准备 1.搭建O…

Windows11 + Ubuntu 24.10

我在win11安装Ubuntu主板:华硕主板Z790 DARK HERO,进入安装,所以文章中bios系统设置为华硕的bios系统。 一、确认系统信息-BIOS为UEFL 备注:UEFL优于MBR,具体可以查询问ai。如果BIOS模式中不是UEFL,建议为UEFL 1、 win+R 输入 msinfo32,打开系统信息,可以看到…

printf详解

printf("hello \nworld\n")&#xff1a;将hello word打印到屏幕上&#xff0c;在使用printf函数时可以多次使用换行符\n&#xff0c;想在哪里加都可以 int main() {printf("hello \nworld\n");return 0; } 占位符&#xff1a;在printf中&#xff0c;占位…

delphi制作漂亮的农历窗体(IntraWeb+Layui的完美结合)

delphi制作漂亮的农历窗体&#xff08;IntraWebLayui的完美结合&#xff09; 不需要安装服务器&#xff0c;Apache和IIS都不需要&#xff0c;自带企业级服务器。 运行exe服务器就架好了&#xff0c;直接打开手机浏览器或者电脑浏览器&#xff0c;网页就出来了&#xff0c;如果…

AI驱动TDSQL-C Serverless 数据库技术实战营-颠覆传统分析模式:智能体与TDSQL-C结合实现人才的可视化数据分析

文章目录 前言云数据库的对比传统云数据库&#xff1a;TDSQL-C Serverless: 智能体与TDSQL-C的结合思路 算力服务器与数据库服务器申请与部署购买 TDSQL-C Mysql Serverless 实例购买HAI高算力服务器 准备工作准备数据下载依赖 案例开发创建数据库开启智能体与TDSQL-C结合 总结…

智能新宠:BabyAlpha A2开启家庭机器人新时代

具身智能领域的“疯狂”&#xff0c;已经迈入了全新的阶段&#xff01;让我们一起来看看这段视频&#xff1a;一个人形机器人在前面奔跑&#xff0c;一群机器狗紧随其后&#xff1b;接着是人追赶机器狗&#xff0c;随后机器狗又追逐人……视频最后&#xff0c;那个机器人似乎还…

【Python】Daphne:Django 异步服务的桥梁

Daphne 是 Django Channels 项目的一部分&#xff0c;专门用于为 Django 提供支持 HTTP、WebSocket、HTTP2 和 ASGI 协议的异步服务器。Daphne 是一个开源的 Python 异步服务器&#xff0c;它可以帮助开发者运行异步应用程序&#xff0c;并且非常适合与 Django Channels 一起使…