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

news/2024/7/15 18:33:49 标签: golang, react.js, 开发语言

后端仓库地址

地址

项目依赖

# 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 initialize

import (
	"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 initialize

import (
	"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.RouterPrefix
	global.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 initialize

import (
	"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.Password
	username := global.GVA_CONFIG.Mysql.Username
	port := global.GVA_CONFIG.Mysql.Port
	dbName := global.GVA_CONFIG.Mysql.Dbname
	dsn := 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 name
		DefaultStringSize:         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会在表明后加s
			NameReplacer:        nil,   // 字符转转换器,转换字段名
			NoLowerCase:         false, //当设置为true时,NoLowerCase选项将禁用表名和列名的蛇形命名转换。保持表名和列名的原始大小写形式。
			IdentifierMaxLength: 0,     //不限制数据库标识符(如表名、列名)的最大长度。
		},
		Logger: logger.New(
			log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
			logger.Config{
				SlowThreshold:             time.Second,   // Slow SQL threshold
				LogLevel:                  logger.Silent, // Log level
				IgnoreRecordNotFoundError: true,          // Ignore ErrRecordNotFound error for logger
				ParameterizedQueries:      true,          // Don't include params in the SQL log
				Colorful:                  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 initialize

import (
	"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 initialize

import (
	"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 string
	if len(path) == 0 {
		flag.StringVar(&configFile, "c", "", "choose config file.")
		flag.Parse()
		if configFile == "" { // 判断命令行参数是否为空
			switch gin.Mode() {
			case gin.DebugMode:
				configFile = enum.ConfigDefaultFile
				fmt.Printf("您正在使用gin模式的%s环境名称,config的路径为%s\n", gin.Mode(), enum.ConfigDebugFile)
			case gin.ReleaseMode:
				configFile = enum.ConfigReleaseFile
				fmt.Printf("您正在使用gin模式的%s环境名称,config的路径为", gin.Mode(), enum.ConfigReleaseFile)
			case gin.TestMode:
				configFile = enum.ConfigTestFile
				fmt.Printf("您正在使用gin模式的%s环境名称,config的路径为%s\n", gin.Mode(), enum.ConfigTestFile)
			}
		} else { // 命令行参数不为空 将值赋值于config
			fmt.Printf("您正在使用命令行的-c参数传递的值,config的路径为%s\n", configFile)
		}
	} else { // 函数传递的可变参数的第一个值赋值于config
		configFile = 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))
	}
	// 当配置文件变化调用此hook
	v.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 model

import (
	"github.com/google/uuid"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Username   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 model

import (
	"gorm.io/gorm"
)

type Backlog struct {
	gorm.Model
	BacklogContent  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 router

import (
	"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.niftyadmin.cn/n/5460878.html

相关文章

HTML——2.属性、标题、段落

一、属性 属性提供了关于元素的额外信息,这些信息可以是元素的行为、样式或其他特性。属性以名称/值对的形式出现,通常写在开始标签中。让我们来看一些常见的HTML属性及其用法: 1. id 属性 id 属性用于为元素指定唯一的标识符。通过 id 属…

Superset二次开发之环境搭建Clickhouse(Linux版)

1.设置ClickHouse仓库 执行以下命令,设置ClickHouse的官方仓库 yum install -y yum-utils yum-config-manager --add-repo https://packages.clickhouse.com/rpm/clickhouse.repo 2.安装ClickHouse 安装ClickHouse的服务器和客户端组件 yum install -y clickhouse-server c…

Adaboost集成学习 | Matlab实现基于ELM-Adaboost极限学习机结合Adaboost集成学习时间序列预测(股票价格预测)

目录 效果一览基本介绍模型设计程序设计参考资料效果一览 基本介绍 基于ELM-Adaboost极限学习机结合Adaboost集成学习时间序列预测(股票价格预测) 单变量时间序列单步预测。 ELM(Extreme Learning Machine,极限学习机)和AdaBoost(Adaptive Boosting,自适应提升)都是机…

量化交易入门(三十)回测框架backtrader-Feeds

前面我们通过几个指标的回测对backtrader的强大有一定的了解,我们将深入学习Backtrader的Feeds,Cerebro,Observers和Strategy等各个模块。 Backtrader的Feeds模块提供了灵活的数据加载和处理功能,支持多种数据源和格式。 Backtrader中的数据…

【linux】Ubuntu 查询CPU、GPU、硬盘、内存等硬件信息

环境 硬件:通用PC /Jetson Xavier NX 套件 系统:Ubuntu 20.04 软件 : 获取CPU信息 在Ubuntu系统中,可以通过在终端执行以下命令来获取CPU的名称: lscpu如果需要精准查找CPU名称 、核心数、厂商可以使用 查看CPU名…

【力扣】191.位 1 的个数、485.最大连续 1 的个数

191.位 1 的个数 题目描述 编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中 设置位 的个数(也被称为汉明重量)。 示例 1: 输入:n 11 输出&#xff1…

岭师大数据技术原理与应用-第二章-环境部署-软工版

HeZaoCha-CSDN博客 环境部署 一、安装包的传输与解压1. XFTP 传输文件2. XTerminal 传输文件3. 解压安装包 二、配置环境变量1. JAVA_HOME2. HADOOP_HOME3. HBASE_HOME4. HIVE_HOME5. 加载环境变量6. 卸载原有 jdk7. 总结 三、安装部署1. MySQL2. Hadoop(1) hadoop.env.sh(2) c…

AE——重构数字(Pytorch+mnist)

1、简介 AE(自编码器)由编码器和解码器组成,编码器将输入数据映射到潜在空间,解码器将潜在表示映射回原始输入空间。AE的训练目标通常是最小化重构误差,即尽可能地重构输入数据,使得解码器输出与原始输入尽…