Go-React做一个todolist(服务端)【一】项目初始化

后端仓库地址

地址

项目依赖

# gin
go get -u github.com/gin-gonic/gin
# viper日志
go get -u github.com/spf13/viper
# 数据库和gorm
go get -u gorm.io/driver/mysql
go get -u gorm.io/gorm
# uuid
go get -u github.com/google/uuid
# token
go get -u github.com/golang-jwt/jwt/v5
# 邮箱
go get github.com/jordan-wright/email
# swagger
go get -u github.com/swaggo/swag/cmd/swag
go install github.com/swaggo/swag/cmd/swag@latest
go get -u github.com/swaggo/files
go get -u github.com/swaggo/gin-swagger# base64验证码
go get -u github.com/mojocn/base64Captcha
# gokit 工具集合
go get github.com/songzhibin97/gkit

项目结构搭建

先执行 go mod init ToDoList
在这里插入图片描述

初始化模块

在initialize/index.go中

package initializeimport ("ToDoList/global""fmt"
)func Works() {// 读取配置文件global.GVA_VIPER = Viper()// 初始化缓存组件Cache.InitCache()// 初始化数据库并注册表global.GVA_DB = GormMysql.InitGormMysql()GormMysql.TableInit()// 启动服务global.GVA_SERVER = GinEngine.InitEngine()if global.GVA_SERVER != nil {// 注册中间件GinEngine.InitMiddleware()// 注册路由GinEngine.InitRouter()// 运行服务global.GVA_SERVER.Run(fmt.Sprintf(":%s", global.GVA_CONFIG.App.Port))}
}

在这里插入图片描述

gin初始化

在initialize/gin.go中

package initializeimport ("ToDoList/docs""ToDoList/global""ToDoList/middleware""ToDoList/router""github.com/gin-gonic/gin"swaggerFiles "github.com/swaggo/files"ginSwagger "github.com/swaggo/gin-swagger"
)type ginEngine struct{}// 初始化中间件
func (receiver ginEngine) InitMiddleware() {// cors跨域中间件global.GVA_SERVER.Use(middleware.CorsByRules())// swagger中间件docs.SwaggerInfo.BasePath = global.GVA_CONFIG.App.RouterPrefixglobal.GVA_SERVER.GET(global.GVA_CONFIG.App.RouterPrefix+"/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
}// 初始化路由
func (receiver *ginEngine) InitRouter() {// 全局路由前缀globalRouterGroup := global.GVA_SERVER.Group(global.GVA_CONFIG.App.RouterPrefix)router.UserRouter.InitUserRouter(globalRouterGroup)
}// 初始化Gin引擎
func (receiver *ginEngine) InitEngine() *gin.Engine {r := gin.Default()return r
}var GinEngine = new(ginEngine)

gorm初始化

在initialize/gorm.go中

package initializeimport ("ToDoList/global""ToDoList/model""fmt""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger""gorm.io/gorm/schema""log""os""time"
)type gormMysql struct{}func (receiver *gormMysql) TableInit() {err := global.GVA_DB.AutoMigrate(model.User{},model.Backlog{},)if err != nil {fmt.Println("注册表发生错误:", err)panic("初始化表失败")}fmt.Println("~~~The database table is successfully registered~~~")
}func (receiver *gormMysql) InitGormMysql() *gorm.DB {password := global.GVA_CONFIG.Mysql.Passwordusername := global.GVA_CONFIG.Mysql.Usernameport := global.GVA_CONFIG.Mysql.PortdbName := global.GVA_CONFIG.Mysql.Dbnamedsn := fmt.Sprintf("%s:%s@tcp(127.0.0.1:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", username, password, port, dbName)db, err := gorm.Open(mysql.New(mysql.Config{DSN:                       dsn,   // DSN data source nameDefaultStringSize:         256,   // string 类型字段的默认长度 如果该字段是字符串并作为主键会造成索引超长DisableDatetimePrecision:  true,  // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持DontSupportRenameIndex:    true,  // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引DontSupportRenameColumn:   true,  // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置}), &gorm.Config{ //连接的配置SkipDefaultTransaction: false, // 默认false,增删改都是事务操作来保证数据一致性,能提升一点性能NamingStrategy: schema.NamingStrategy{TablePrefix:         "",    // 如果设置了会给每个表名加前缀SingularTable:       true,  // 单数表名,如果false会在表明后加sNameReplacer:        nil,   // 字符转转换器,转换字段名NoLowerCase:         false, //当设置为true时,NoLowerCase选项将禁用表名和列名的蛇形命名转换。保持表名和列名的原始大小写形式。IdentifierMaxLength: 0,     //不限制数据库标识符(如表名、列名)的最大长度。},Logger: logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags), // io writerlogger.Config{SlowThreshold:             time.Second,   // Slow SQL thresholdLogLevel:                  logger.Silent, // Log levelIgnoreRecordNotFoundError: true,          // Ignore ErrRecordNotFound error for loggerParameterizedQueries:      true,          // Don't include params in the SQL logColorful:                  false,         // Disable color},), // 可以自定义日志DisableForeignKeyConstraintWhenMigrating: true, //true时,建表将不会建立物理外键,代码中我们采用逻辑外键提升数据库操作效率})if err != nil {panic(err.Error())}sqlDB, _ := db.DB()sqlDB.SetMaxIdleConns(global.GVA_CONFIG.Mysql.MaxIdleConns)sqlDB.SetMaxOpenConns(global.GVA_CONFIG.Mysql.MaxOpenConns)return db
}var GormMysql = new(gormMysql)

缓存kit初始化

在initialize/cache.go中

package initializeimport ("ToDoList/global""ToDoList/util""github.com/songzhibin97/gkit/cache/local_cache"
)type cache struct{}func (receiver *cache) InitCache() {dr, err := util.BasicUtils.ParseDuration(global.GVA_CONFIG.JWT.ExpiresTime)if err != nil {panic(err)}global.BlackCache = local_cache.NewCache(local_cache.SetDefaultExpire(dr),)
}var Cache = new(cache)

读取配置文件Viper初始化

package initializeimport ("ToDoList/enum""ToDoList/global""flag""fmt""github.com/fsnotify/fsnotify""github.com/gin-gonic/gin""github.com/spf13/viper"
)// Viper //
// 优先级: 命令行 > 环境变量 > 默认值
// Author [SliverHorn](https://github.com/SliverHorn)
func Viper(path ...string) *viper.Viper {var configFile stringif len(path) == 0 {flag.StringVar(&configFile, "c", "", "choose config file.")flag.Parse()if configFile == "" { // 判断命令行参数是否为空switch gin.Mode() {case gin.DebugMode:configFile = enum.ConfigDefaultFilefmt.Printf("您正在使用gin模式的%s环境名称,config的路径为%s\n", gin.Mode(), enum.ConfigDebugFile)case gin.ReleaseMode:configFile = enum.ConfigReleaseFilefmt.Printf("您正在使用gin模式的%s环境名称,config的路径为", gin.Mode(), enum.ConfigReleaseFile)case gin.TestMode:configFile = enum.ConfigTestFilefmt.Printf("您正在使用gin模式的%s环境名称,config的路径为%s\n", gin.Mode(), enum.ConfigTestFile)}} else { // 命令行参数不为空 将值赋值于configfmt.Printf("您正在使用命令行的-c参数传递的值,config的路径为%s\n", configFile)}} else { // 函数传递的可变参数的第一个值赋值于configconfigFile = path[0]fmt.Printf("您正在使用func Viper()传递的值,config的路径为%s\n", configFile)}// 初始化Viper對象v := viper.New()// 设置配置文件的路径v.SetConfigFile(configFile)// 配置文件类型v.SetConfigType("yaml")err := v.ReadInConfig()if err != nil {panic(fmt.Errorf("Fatal error config file: %s \n", err))}// 当配置文件变化调用此hookv.OnConfigChange(func(e fsnotify.Event) {fmt.Println("config file changed:", e.Name)if err = v.Unmarshal(&global.GVA_CONFIG); err != nil {fmt.Println(err)}})// 配置文件变动会重读不必重启服务v.WatchConfig()if err = v.Unmarshal(&global.GVA_CONFIG); err != nil {panic(err)}return v
}

模型

用户

package modelimport ("github.com/google/uuid""gorm.io/gorm"
)type User struct {gorm.ModelUsername   string    `json:"userName" gorm:"comment:用户名"`NickName   string    `json:"nickName" gorm:"comment:昵称"`Password   string    `json:"password" gorm:"comment:密码"`Identity   string    `json:"身份" gorm:"comment:用户身份"`Email      string    `json:"email" gorm:"comment:用户邮箱"`UUID       uuid.UUID `json:"uuid" gorm:"index;comment:用户UUID"`Avatar     string    `json:"avatar" gorm:"comment:用户头像;default:https://fancyfish.top/hero.jpg"`ThemeColor string    `json:"themeColor" gorm:"comment:用户主题颜色"`Enable     bool      `json:"enable" gorm:"comment:用户是否可用;default:true"`Backlog    Backlog
}func (receiver User) TableName() string {return "user"
}

待办事项

package modelimport ("gorm.io/gorm"
)type Backlog struct {gorm.ModelBacklogContent  string    `json:"backlogContent" gorm:"comment:代办事项内容"`Completed       bool      `json:"completed" gorm:"comment:是否完成;default:false"`UserId          uint      `json:"user_id"`ParentId        *uint     `json:"parent_id"`ChildrenBacklog []Backlog `gorm:"foreignkey:ParentId;"`
}func (receiver Backlog) TableName() string {return "backlog"
}

路由

package routerimport ("ToDoList/api""github.com/gin-gonic/gin"
)type userRouter struct{}func (receiver userRouter) InitUserRouter(R *gin.RouterGroup) {r := R.Group("user"){r.POST("register", api.UserApi.Register)r.POST("login", api.UserApi.Login)r.POST("change_password", api.UserApi.ChangePassword)r.PUT("set_userinfo", api.UserApi.SetSelfInfo)r.GET("get_userInfo", api.UserApi.GetUserInfo)r.POST("get_captcha", api.UserApi.GetCaptcha)}
}var UserRouter = new(userRouter)

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

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

相关文章

postcss安装和使用(详细)

1,安装postcss: 在此之前需要安装有node.js 第一步 命令:cnpm install postcss-cli -g 第二步 命令:cnpm install postcss –g 推荐内容 2,下载autoprefixer插件,并创建postcss.config.js文件并写入配置代码 autoprefixer插件…

HCIP【GRE VPN、MGRE VPN与PPP验证综合实验】

目录 实验要求: 实验拓扑图: 实验思路: 实验步骤: 一、配IP地址 (1)配置所有设备接口的IP地址: (2)配置私网与公网接口的缺省路由使得公网可通: 二、P…

基于boost准标准库的搜索引擎项目

零 项目背景/原理/技术栈 1.介绍boost准标准库 2.项目实现效果 3.搜索引擎宏观架构图 这是一个基于Web的搜索服务架构 该架构优点: 客户端-服务器模型:采用了经典的客户端-服务器模型,用户通过客户端与服务器交互,有助于集中管理和分散计算…

设计模式6--抽象工厂模式

定义 案例一 案例二 优缺点

MacOS M1/M2/M3芯片如何安装Python3.6

前言 Mac电脑M芯片安装Python3.6报错。 一般情况下,Mac系统可以使用homebrew来管理安装软件。 brew search搜索发现,最低只能直接安装python3.7版本。 于是从Python官网下载安装包进行安装,确实也没有报错,安装完成后执行总是k…

【自动装箱以及包装类的缓存】⭐️通过具体案例看下每种包装类的不同结果

目录 前言 一、自动装箱与拆箱(以 Integer 包装类为例) 二、再来看看几个示例 ​编辑三、Double ,Float 类型亦是如此吗? 前言 小伙伴们大家好,日常使用业务层方面的代码居多,但也不可忘了基本的一些代码格式以及原…

ubuntu22.04@Jetson Orin Nano安装配置VNC服务端

ubuntu22.04Jetson Orin Nano安装&配置VNC服务端 1. 源由2. 环境3. VNC安装Step 1: update and install xserver-xorg-video-dummyStep 2: Create config for dummy virtual displayStep3: Add the following contents in xorg.conf.dummyStep 4: Update /etc/X11/xorg.con…

设计模式7--建造者模式

定义 案例一 案例二 优缺点

面试题1(京东)之HiveSql --- 难度:入门初级

第1题 有如下的用户访问数据 userIdvisitDatevisitCountu012017/1/215u022017/1/236u032017/1/228u042017/1/203u012017/1/236u012017/2/218u022017/1/236u012017/2/224 要求使用SQL统计出每个用户的累积访问次数,如下表所示: 用户id月份小计累积u01…

《云原生安全攻防》-- K8s集群安全风险分析

在这个数字化快速发展的年代,云原生安全变得越来越重要。我明白对于很多朋友来说,这是一个既新奇又复杂的领域。因此,我整合了以往的专业积累,精心打造了一个专门讲解云原生安全的系列课程,目的是能给大家带来有价值的…

微信小程序备案流程详细操作指南

自2023年9月1日起,所有新上架的微信小程序均需事先完成备案手续,方能成功上线。而对于已经上架的存量小程序,也需要在2024年3月31日前完成备案工作。若在规定时间内未完成备案,平台将依据备案相关规定,自2024年4月1日起…

TC16-161T+ 音频 信号变压器 RF Transformers 600kHz-160MHz 射频集成电路 Mini-Circuits

Mini-Circuits是一家全球领先的射频、微波和毫米波元器件及子系统制造商。TC16-161T是Mini-Circuits出产的一款射频IC(射频集成电路),具有平衡-不平衡转换器功用。制造商: Mini-Circuits 产品品种: 音频变压器/信号变压器 RoHS…

Git 如何合并多个连续的提交

我平常的编程喜欢是写一段代码就提交一次,本地一般不攒代码,生怕本地有什么闪失导致白干。但这样就又导致一个问题:查看历史日志时十分不方便,随便找一段提交可以看到: > git log --oneline 8f06be5 add 12/qemu-h…

OSPF基本原理和概念

文章目录 背景知识OSPF协议概述:OSPF区域的表示OSPF 骨干区域 –区域0OSPF 非骨干区域 -非0区域OSPF的五种区域类型OSPF工作原理OSPF 的报文类型OSPF邻居表中的七个状态 总结 背景知识 一台路由设备如何获取其他网段的路由,并加入到路由表中 直连路由 …

腾讯云2核2G服务器优惠价格,61元一年

腾讯云2核2G服务器多少钱一年?轻量服务器61元一年,CVM 2核2G S5服务器313.2元15个月,轻量2核2G3M带宽、40系统盘,云服务器CVM S5实例是2核2G、50G系统盘。腾讯云2核2G服务器优惠活动 txybk.com/go/txy 链接打开如下图:…

Etag:HTTP缓存控制机制解析

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

无论PC还是Mac,都能畅快地使用移动硬盘 Mac使用NTFS移动硬盘不能读写

如果你拥有一台Mac设备,总会遇到尴尬的那一刻——你在Mac上用得好好的移动硬盘怎么都不能被PC识别到。又或者你朋友在PC上用得好好的移动硬盘,连上你的Mac后,Mac里的文件死活就是拷贝不进移动硬盘里。这种坑,相信大多数使用Mac的小…

.NET使用HttpClient以multipart/form-data形式post上传文件及其相关参数

前言: 本次要讲的是使用.Net HttpClient拼接multipark/form-data形式post上传文件和相关参数,并接收到上传文件成功后返回过来的结果(图片地址,和是否成功)。可能有很多人会说用ajax不是就可以轻松的实现吗&#xff1f…

生信数据分析——GO+KEGG富集分析

生信数据分析——GOKEGG富集分析 目录 生信数据分析——GOKEGG富集分析1. 富集分析基础知识2. GO富集分析(Rstudio)3. KEGG富集分析(Rstudio) 1. 富集分析基础知识 1.1 为什么要做功能富集分析? 转录组学数据得到的基…

java多线程——概述,创建方式及常用方法

前言: 学习到多线程了,整理下笔记,daydayup!!! 多线程 什么是线程 线程(Thread)是一个程序内部的一条执行流程。若程序只有一条执行流程,那这个程序就是单线程的程序。 什么是多线程 多线程是指从软硬件上…