基于Go+vue3+ts博客项目实战第一篇(后端项目搭建)
·
基于Go+vue3+ts博客项目实战第一篇
后端项目搭建
go代理
GOPROXY=https://goproxy.cn,direct
项目结构
- api:接口目录
- config:存放记录配置的结构体目录
- core:初始化操作
- docs:swag生成的api文档目录
- flag:命令行相关的初始化
- global:全局变量的包
- middleware:中间件
- models:表结构
- routers:gin路由的目录
- service:项目与服务有关的目录
- testdata:测试文件的目录
- utils:常用的一些工具
- valid:参数校验
- .gitignore:代码上传git忽略的文件
- go.mod:项目所需要的依赖
- main.go:程序的入口
- settings.yml:配置文件
配置文件编写
这里是一部分,后续还会添加一些其他的配置如:redis、es、服务网关
# mysql配置
mysql:
host: 127.0.0.1
port: 3306
username: root
password: root
db: gvb_db
log_level: dev # 日志级别
# 日志配置
logger:
level: info
prefix: '[gvb]'
director: log
show_line: true
log_in_console: true
# 系统配置
system:
host: "0.0.0.0"
port: 8080
env: dev # 开发环境
结构体编写
mysql
package config
type Mysql struct {
Host string `yaml:"host"`
Port string `yaml:"port"`
User string `yaml:"user"`
Password string `yaml:"password"`
DB string `yaml:"db"`
LogLevel string `yaml:"log_level"` // 日志级别 debug就是输出全部
}
system
package config
import "fmt"
type System struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
Env string `yaml:"env"`
}
// Addr 获取项目地址
func (s System) Addr() string {
return fmt.Sprintf("%s:%d", s.Host, s.Port)
}
logger
package config
type Logger struct {
Level string `yaml:"level"` // 日志级别
Prefix string `yaml:"prefix"` // 输出日志前缀
Director string `yaml:"director"` // 日志保存的目录
ShowLine bool `yaml:"showLine"` // 是否显示行号 true:显示 false:不显示
LogInConsole bool `yaml:"logInConsole"` // 是否将日志输出到控制台上 true:是 false:否
}
enter
package config
type Config struct {
Mysql Mysql `yaml:"mysql"`
Logger Logger `yaml:"logger"`
System System `yaml:"system"`
}
读取配置文件
安装yaml解析器
go get -u gopkg.in/yaml.v2
需要一个全局变量,用于保存配置文件,存放在global目录下
package global
import "gvb_server/config"
var (
Config *config.Config
)
读取配置文件
package core
import (
"fmt"
"gopkg.in/yaml.v2"
"gvb_server/config"
"gvb_server/global"
"io/ioutil"
"log"
)
// InitConf 读取配置文件
func InitConf() {
const ConfigFile = "settings.yml"
c := &config.Config{}
file, err := ioutil.ReadFile(ConfigFile)
if err != nil {
panic(fmt.Errorf("get yamlConf error: %s", err))
}
err = yaml.Unmarshal(file, c)
if err != nil {
log.Fatalf("config Init Unmarshal: %v", err)
}
log.Println("config yamlFile load Init success.")
global.Config = c
}
然后在main中调用init.conf
package main
import (
"fmt"
"gvb_server/core"
"gvb_server/global"
)
//TIP <p>To run your code, right-click the code and select <b>Run</b>.</p> <p>Alternatively, click
// the <icon src="AllIcons.Actions.Execute"/> icon in the gutter and select the <b>Run</b> menu item from here.</p>
func main() {
core.InitConf()
fmt.Println(global.Config)
}
mac系统配置mysql
在命令行中输入uname -a查询电脑配置信息,找到对应需要下载的mysql版本
-
下载完后双击进入安装 ,一直到Configuration,选择上面那一个Use Strong Password Encryption,点击Next进入下一步写你的root密码;
-
打开系统设置在里面找到MySQL,查看mysql是否正常启动

-
接下来打开终端验证MySQL是否配置成功,输入mysql,如果显示
zsh:command not find :mysql,就是还没有配置成功,此时在终端输入sudo vim ~/.zshrc,这里会让你输入密码是你电脑的密码;- 进入文件后输入a进入编辑模式

/usr/local/mysql-8.0.40-macos14-arm64/bin是你的MySQL安装地址,mysql默认安装在/usr/local/文件夹下- 编辑完成后按下键盘上的
esc,退出编辑模式,输入:wq保存并退出配置文件 - 继续在终端输入
source ~/.zshrc使配置文件生效 - 终端输入mysql -uroot -p,随后输入密码
- 出现这个界面说明
mysql配置成功

- 进入文件后输入a进入编辑模式
最后打开数据库可视化工具Navicat,测试连接数据库
Navicat官方下载地址

至此mysql环境配置完成
gorm配置
gorm初始化
安装依赖包
# mysql驱动
go get -u gorm.io/driver/mysql
# gorm包
go get -u gorm.io/gorm
package core
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gvb_server/global"
"log"
"time"
)
func InitGorm() *gorm.DB {
if global.Config.Mysql.Host == "" {
log.Println("未配置mysql,取消gorm连接")
return nil
}
dsn := global.Config.Mysql.Dsn()
var mysqlLogger logger.Interface
if global.Config.System.Env == "debug" {
// 开发环境显示所有的sql
mysqlLogger = logger.Default.LogMode(logger.Info)
} else {
mysqlLogger = logger.Default.LogMode(logger.Error) // 只打印错误的sql
}
//global.MysqlLog = logger.Default.LogMode(logger.Info)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: mysqlLogger,
})
if err != nil {
log.Fatalf(fmt.Sprintf("[%s] mysql连接失败", dsn))
}
sqlDB, _ := db.DB()
sqlDB.SetMaxIdleConns(10) // 最大空闲连接数
sqlDB.SetMaxOpenConns(100) // 最多可容纳
sqlDB.SetConnMaxLifetime(time.Hour * 4) // 连接最大复用时间,不能超过mysql的wait_timeout
return db
}
logrus日志配置
安装依赖包
go get -u github.com/sirupsen/logrus
初始化日志
package core
import (
"bytes"
"fmt"
"github.com/sirupsen/logrus"
"gvb_server/global"
"os"
"path"
)
// 颜色
const (
red = 31
yellow = 33
blue = 36
gray = 37
)
type LogFormatter struct{}
// Format 实现Formatter(entry *logrus.Entry) ([]byte, error)接口
func (t *LogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
//根据不同的level去展示颜色
var levelColor int
switch entry.Level {
case logrus.DebugLevel, logrus.TraceLevel:
levelColor = gray
case logrus.WarnLevel:
levelColor = yellow
case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel:
levelColor = red
default:
levelColor = blue
}
var b *bytes.Buffer
if entry.Buffer != nil {
b = entry.Buffer
} else {
b = &bytes.Buffer{}
}
log := global.Config.Logger
//自定义日期格式
timestamp := entry.Time.Format("2006-01-02 15:04:05")
if entry.HasCaller() {
//自定义文件路径
funcVal := entry.Caller.Function
fileVal := fmt.Sprintf("%s:%d", path.Base(entry.Caller.File), entry.Caller.Line)
//自定义输出格式
fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m %s %s %s\n", log.Prefix, timestamp, levelColor, entry.Level, fileVal, funcVal, entry.Message)
} else {
fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m %s\n", log.Prefix, timestamp, levelColor, entry.Level, entry.Message)
}
return b.Bytes(), nil
}
func InitLogger() *logrus.Logger {
mLog := logrus.New() //新建一个实例
mLog.SetOutput(os.Stdout) //设置输出类型
mLog.SetReportCaller(global.Config.Logger.ShowLine) //开启返回函数名和行号
mLog.SetFormatter(&LogFormatter{}) //设置自己定义的Formatter
level, err := logrus.ParseLevel(global.Config.Logger.Level)
if err != nil {
level = logrus.InfoLevel
}
mLog.SetLevel(level) //设置最低的Level
InitDefaultLogger()
return mLog
}
func InitDefaultLogger() {
// 全局log
logrus.SetOutput(os.Stdout) //设置输出类型
logrus.SetReportCaller(global.Config.Logger.ShowLine) //开启返回函数名和行号
logrus.SetFormatter(&LogFormatter{}) //设置自己定义的Formatter
level, err := logrus.ParseLevel(global.Config.Logger.Level)
if err != nil {
level = logrus.InfoLevel
}
logrus.SetLevel(level) //设置最低的Level
}
封装统一响应
package res
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Response struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data any `json:"data"`
}
const (
Success = 0 // 请求成功状态码
Error = 7 // 请求失败状态码
)
func Result(code int, msg string, data any, c *gin.Context) {
c.JSON(http.StatusOK, Response{
code, msg, data,
})
}
func OK(code int, msg string, data any, c *gin.Context) {
Result(code, msg, data, c)
}
func OKWithData(data any, c *gin.Context) {
Result(Success, "ok", data, c)
}
func OKWithMsg(msg string, c *gin.Context) {
Result(Success, msg, map[string]any{}, c)
}
func Fail(code int, msg string, data any, c *gin.Context) {
Result(code, msg, data, c)
}
func FailWithMsg(msg string, c *gin.Context) {
Result(Error, msg, map[string]any{}, c)
}
func FailWithCode(code ErrorCode, c *gin.Context) {
msg, ok := ErrorMap[code]
if ok {
Result(int(code), msg, map[string]any{}, c)
}
Result(int(Error), "系统未知错误", map[string]any{}, c)
}
自定义业务异常状态码
package res
type ErrorCode int
const (
SettingsError ErrorCode = 1001
)
var (
ErrorMap = map[ErrorCode]string{
SettingsError: "Settings Error",
}
)
路由初始化(路由分组)
package routers
import (
"github.com/gin-gonic/gin"
)
type RouterGroup struct {
*gin.RouterGroup
}
func InitRouter() *gin.Engine {
router := gin.Default()
apiRouterGroup := router.Group("api")
routerGroupApp := RouterGroup{apiRouterGroup}
routerGroupApp.SettingsRouter()
return router
}
package routers
import (
"gvb_server/api"
)
func (router RouterGroup) SettingsRouter() {
settingsApi := api.ApiGroupApp.SettingsApi
router.GET("settings", settingsApi.SettingsInfoView)
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)