后端项目搭建

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

mysql官网
在这里插入图片描述

在命令行中输入uname -a查询电脑配置信息,找到对应需要下载的mysql版本

  1. 下载完后双击进入安装 ,一直到Configuration,选择上面那一个Use Strong Password Encryption,点击Next进入下一步写你的root密码;

  2. 打开系统设置在里面找到MySQL,查看mysql是否正常启动
    在这里插入图片描述

  3. 接下来打开终端验证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配置成功
      出现这个界面说明mysql配置成功

最后打开数据库可视化工具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)
}
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐