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插件…

专升本-机器人流程化自动化(RPA)

一般考选择,题目较少 ,2018年中国步入RPA应用元年 机器人流程化自动化(RPA) Robotic process automation,RPA 1. 定义:(是一个软件系统,不是硬件)是以软件机器人和人工…

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

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

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

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

OpenCV联通组件扫描

注:黑色背景 void ccl_demo() {QString appPath QCoreApplication::applicationDirPath();QString imagePath appPath "/rice.png";Mat img cv::imread(imagePath.toStdString());if (img.empty()) {return;}namedWindow("input", WINDOW_A…

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

定义 案例一 案例二 优缺点

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

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

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

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

git 查看文件夹结构树

在Git中,没有直接的命令可以像文件系统那样展示一个可视化的文件结构树。但是,你可以使用一些外部工具或命令来达到这个目的。 以下是一些方法,你可以使用它们来查看Git仓库的文件结构树: 使用tree命令(如果你的系统已…

采药采药~

题源 背包 #include<bits/stdc.h> using namespace std; struct medi{int t,v; }md[1110]; int t1,m; int dp[1110][1110]{0}; int main() {cin>>t1>>m;for(int i1;i<m;i){cin>>md[i].t>>md[i].v;}for(int i1;i<m;i){for(int j1;j<t1…

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--建造者模式

定义 案例一 案例二 优缺点

专升本-区块链

区块链 定 义&#xff1a;一种新的数据记录&#xff0c;存储&#xff0c;表达的方式。参加区块链的全体成员都有一份数据&#xff0c;以及每个人对数据进行的操作都会被区块链里的每个人得知。这样就可以避免都存储在一个地方导致数据丢失后造成的损失 发展历程&#xff1a; …

【BlossomRPC】编解码器的实现

文章目录 RPC项目 配置中心项目 网关项目 在前面的文章了解完毕之后&#xff0c;我们以及设计了一个基本的RPC协议&#xff0c;之后&#xff0c;我们要做的就是基于这个RPC协议&#xff0c;去实现一个能解析这个RPC协议的编解码器。 这里编解码器比较容易写&#xff0c;按照…

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

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

Java-代理模式

1、什么是代理模式 代理&#xff1a;自己不做&#xff0c;找别人帮你做 代理模式&#xff1a;在一个原有功能的基础上添加新的功能 分类&#xff1a;静态代理和动态代理 2、静态代理 原有方式&#xff1a;就是将核心业务和服务方法都编写在一起 package com.AE.service;p…

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

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

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

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

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

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

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

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