è¿æ¯ææåä¸æ建ç第ä¸ä¸ªæ¡æ¶ï¼è¿ç»§ç»ä»¥ä»¥åçé£æ ¼ï¼ä»mainå½æ°å¼å§æ解åæè¿ä¸ªæ¡æ¶ï¼æ¯ç®åææè½æ¥è§¦åå®ç°çä¸ä¸ªæ为æææ¯å«éçgoçå端项ç®æ¡æ¶ã
mainå½æ°
è¿ä¸ªæ³¨éçä½ç¨æ¯swaggerçææ¥å£ææ¡£ç第ä¸æ¥å³ï¼æ·»å 注é
å
·ä½ï¼
@title è¿éåçæ¯æ é¢
@version è¿éæ¯çæ¬å·
@description è¿æ¯å¯¹è¿ä¸ªé¡¹ç®çä¸ä¸ªæè¿°
@contact.name è¿ä¸ªåçæ¯è系人çåå
@contact.url è¿éåçæ¯èç³»ç½å
@contact.email è¿éåçæ¯èç³»é®ç®±
@host è¿éåçæ¯æ¥å£æå¡çhost
@BasePath è¿éåbase path
å®ä¹å½ä»¤è¡flagåæ°ç两ç§æ¹å¼ä¹ä¸
Goè¯è¨å
ç½®çflagå
å®ç°äºå½ä»¤è¡åæ°ç解æï¼flagå
使å¾å¼åå½ä»¤è¡å·¥å
·æ´ä¸ºç®åã
flag.StringVar(typeæéï¼flagåï¼é»è®¤å¼ï¼å¸®å©ä¿¡æ¯)ï¼ç¨æ¥
å®ä¹å¥½oå½ä»¤è¡flagåæ°åï¼è°ç¨flag.Parse()æ¥å¯¹å½ä»¤è¡åæ°è¿è¡è§£æ
æ¯æçå½ä»¤è¡åæ°æ ¼å¼æ以ä¸å ç§ï¼
config.Setup()该æ¹æ³çä½ç¨æ¯è½½å ¥é ç½®æ件ï¼å ·ä½å¦ä¸ï¼è®²è§£ä¸ä¸configï¼ï¼
è¿ä¸ªæ件代ç è¾å¤ï¼æ¶åä¹è¾å¹¿ï¼å ·ä½å¦ä¸ï¼
ä¸é¢è¿äºåéæ¯åæ ãåå ï¼ææé
ç½®åå¨ä¸ä¸ªæ件ï¼éé¢æ¯é对ä¸åæ¹é¢çä¸åé
ç½®ï¼æ以使ç¨ä¸é¢è¿ç§æ¹å¼æ¥å®ä¹æ¯ä¸åå¿é
ç½®
// Mysqlé
置项
var cfgMysql *viper.Viper
// åºç¨é
置项
var cfgApplication *viper.Viper
// Tokené
置项
var cfgJwt *viper.Viper
// Logé
置项
var cfgLogger *viper.Viper
// Redisé
置项
var cfgRedis *viper.Viper
ä¸é¢è¿ä¸ªå½æ°çä½ç¨æ¯è½½å ¥é ç½®æ件ï¼æä¼å¯¹å ¶è¿è¡æ解ï¼ä¸å°åä¸å°åç解æï¼ï¼
//è½½å
¥é
ç½®æ件
func Setup(path string) {
}
ä¸é¢è¿ä¸ç³»åæ¹æ³ä½ç¨ï¼
viper.SetConfigFile()æå®é
ç½®æ件
ioutil.ReadFile()读åæ件çæ¹å¼ä¹ä¸ï¼ä¼ å
¥æ件ååï¼è¿åä¸ä¸ªbyte[]åä¸ä¸ªerrï¼ä¼å°æ件çå
容å为ä¸ä¸ªåèæ°ç»è¿åï¼å¦ææ¥éåæå°ã
使ç¨ioutil.ReadFile()注æï¼â ä¸éè¦æå¨ æå¼ä¸å
³éæ件ï¼ç³»ç»ä¼å¸®æ们èªå¨å®æï¼â¡åªéåäºå°æ件
// å è½½é
ç½®æ件
viper.SetConfigFile(path)
content, err := ioutil.ReadFile(path)
if err != nil {
log.Fatal(fmt.Sprintf("Read config file fail: %s", err.Error()))
}
ä¸é¢è¿äºæ¹æ³ä½ç¨ï¼
string(content)ï¼å°[]byteç±»åæ°æ®è½¬ä¸ºstringç±»å
os.ExpandEnv()ï¼æå符串çsæ¿æ¢æç¯å¢åéçå
容ï¼å½æ°çåå½¢æ¯func ExpandEnv(s string) string
strings.NewReader()ï¼å建ä¸ä¸ªä»s读åæ°æ®çReaderï¼è¿åç*Readerä¸çiæçæ¯è¯»åå°çä½ç½®
viper.ReadConfig()ï¼viper æ¯æä»io.Readerä¸è¯»åé
ç½®ãè¿ç§å½¢å¼å¾çµæ´»ï¼æ¥æºå¯ä»¥æ¯æ件ï¼ä¹å¯ä»¥æ¯ç¨åºä¸çæçå符串ï¼çè³å¯ä»¥ä»ç½ç»è¿æ¥ä¸è¯»åçåèæµã
//Replace environment variables
err = viper.ReadConfig(strings.NewReader(os.ExpandEnv(string(content))))
if err != nil {
log.Fatal(fmt.Sprintf("Parse config file fail: %s", err.Error()))
}
viper.Sub()ï¼è®¿é®åµå¥çé®
éè¿ä¼ å ¥.åéçè·¯å¾æ¥è®¿é®åµå¥å段
å°ä¸å模åå¿çé 置信æ¯åç»ä¸åçåéã
ç¶åå¨ä¸åä½ç½®åå§åï¼æ·»å é 置信æ¯ï¼åèªæ¨¡åã
cfgMysql = viper.Sub("settings.mysql")
if cfgMysql == nil {
panic("No found settings.mysql in the configuration")
}
MysqlConfig = InitMySql(cfgMysql)
cfgJwt = viper.Sub("settings.jwt")
if cfgJwt == nil {
panic("No found settings.jwt in the configuration")
}
JwtConfig = InitJwt(cfgJwt)
cfgRedis = viper.Sub("settings.redis")
if cfgRedis == nil {
panic("No found settings.redis in the configuration")
}
RedisConfig = InitRedis(cfgRedis)
ä¸é¢è¿ä¸ªæ¯mysqlæ°æ®åºçåå§åï¼
å®ä¹mysqlç»æä½
ç¶å对å
¶è¿è¡åå§åï¼å¼éè¿viperçæ¹å¼ä¼ éã
è¿åçç±»åæ¯Mysqlç±»åçæé
以ä¸è¿ä¸ç³»åæ¹æ³é½æä¸ä¸ªç¹ç¹ï¼
å³æåä¸è¡ä»£ç ï¼å¾ç¹å«çä¸ç§åæ³ï¼ï¼
声æä¸ä¸ªå¯¹è±¡ä¾å¤é¨ä½¿ç¨ã
ä¸é¢ç代ç å³æ¯è¿ç§æ¹å¼å®ç°çã
type Mysql struct {
User string
Password string
Host string
DbName string
Port int
DbMaxOpen int
DbMaxIdle int
}
// InitMySql åå§åmysqlé
ç½®
func InitMySql(cfg *viper.Viper) *Mysql {
db := &Mysql{
User: cfg.GetString("user"),
Password: cfg.GetString("password"),
Host: cfg.GetString("host"),
DbName: cfg.GetString("dbname"),
Port: cfg.GetInt("port"),
DbMaxOpen: cfg.GetInt("maxopen"),
DbMaxIdle: cfg.GetInt("maxidle"),
}
return db
}
var MysqlConfig = new(Mysql)
ä¸é¢è¿ä¸ªæ¯redisåå§åé ç½®æä½
Rediséçå段ä½ç¨ï¼
poolSize:æ大è¿æ¥æ°ï¼è®¾ç½®ä¸º0åè§æ åµèå®ï¼
IdleTimeOutSec:æ大空é²è¿æ¥æ¶é´
DB:æ°æ®åºï¼redisä¸å ±åå 个æ°æ®åºï¼
Port:端å£
Password:å¯ç (ä¸è¬ä¸è®¾å¯ç )
Host:æå¡å¨å°å
type Redis struct {
PoolSize int
IdleTimeOutSec int
DB int
Port int
Password string
Host string
}
// InitRedis åå§åredisé
ç½®
func InitRedis(cfg *viper.Viper) *Redis {
db := &Redis{
PoolSize: cfg.GetInt("poolsize"),
IdleTimeOutSec: cfg.GetInt("idletimeoutsec"),
DB: cfg.GetInt("db"),
Port: cfg.GetInt("port"),
Host: cfg.GetString("host"),
Password: cfg.GetString("password"),
}
return db
}
var RedisConfig = new(Redis)
ä¸é¢æ¯jwtåå§åé ç½®æä½ï¼å ç+è®¾ç½®è¶ æ¶æ¶é´ï¼
type Jwt struct {
Secret string
Timeout int64
}
// InitJwt åå§åjwté
ç½®
func InitJwt(cfg *viper.Viper) *Jwt {
return &Jwt{
Secret: cfg.GetString("secret"),
Timeout: cfg.GetInt64("timeout"),
}
}
var JwtConfig = new(Jwt)
åå°mainæ¹æ³
// 2. åå§åæ¥å¿
if err := logger.Init(config.LoggerConfig, config.ApplicationConfig.Mode); err != nil {
fmt.Printf("init logger failed, err:%v\n", err)
return
}
defer zap.L().Sync()
zap.L().Debug(utils.Green("logger init success..."))
åå§åæ¥å¿æä½ï¼ä¼ å
¥ä¸¤ä¸ªåæ°ï¼ä¸ä¸ªæ¯æ¥å¿é
置信æ¯ï¼å¦ä¸ä¸ªæ¯æ¨¡å¼ï¼ä¸»è¦æ¯å¼å模å¼åç产模å¼ï¼
ä¸é¢è¿ä¸ªæ¹æ³å°±æ¯åå§åæ¥å¿æä½ï¼è¿åä¸ä¸ªé误ã
主è¦æ¯æ³ä½¿ç¨å®å¶çloggerï¼å°æ¥å¿åå
¥æ件èä¸æ¯ç»ç«¯
å
é¨ä»£ç è§ä¸å¾ï¼
ä¼ å ¥æå®å个åæ°ï¼è¿åä¸ä¸ªzapcore.WriteSyncer对象ï¼ä¸ï¼
writeSyncer := getLogWriter(
cfg.Filename,
cfg.MaxSize,
cfg.MaxBackups,
cfg.MaxAge,
)
encoder := getEncoder()
var l = new(zapcore.Level)
err = l.UnmarshalText([]byte(cfg.Level))
if err != nil {
return
}
var core zapcore.Core
if mode == string(utils.ModeProd) {
// è¿å
¥ç产模å¼
core = zapcore.NewCore(encoder, writeSyncer, l)
} else {
// è¿å
¥å¼å模å¼ææµè¯æ¨¡å¼
consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
core = zapcore.NewTee(
zapcore.NewCore(encoder, writeSyncer, l),
zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stdout), l),
)
}
lg := zap.New(core, zap.AddCaller())
zap.ReplaceGlobals(lg) // æ¿æ¢zapå
ä¸å
¨å±çloggerå®ä¾ï¼åç»å¨å
¶ä»å
ä¸åªé使ç¨zap.L()è°ç¨å³å¯
return
å
·ä½æ¥éª¤ä¸ï¼WriterSyncer ï¼æå®æ¥å¿å°åå°åªéå»ã
ä½æ¯å¦ææ³å®ç°å°æ¥å¿åå²å½æ¡£ï¼åéè¦ä½¿ç¨ç¬¬ä¸æ¹åºLumberjackæ¥å®ç°ï¼
è¦å¨zapä¸å å
¥Lumberjackæ¯æï¼æ们éè¦ä¿®æ¹WriteSyncer代ç
å
¶ä¸Loggerå±æ§çææå¦ä¸ï¼
Filename: æ¥å¿æ件çä½ç½®
MaxSizeï¼å¨è¿è¡åå²ä¹åï¼æ¥å¿æ件çæ大大å°ï¼ä»¥MB为åä½ï¼
MaxBackupsï¼ä¿çæ§æ件çæ大个æ°
MaxAgesï¼ä¿çæ§æ件çæ大天æ°
Compressï¼æ¯å¦å缩/å½æ¡£æ§æ件
æå使ç¨zapcore.AddSync()å½æ°å¹¶ä¸å°æå¼çæ件å¥æä¼ è¿å»
func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: filename,
MaxSize: maxSize,
MaxBackups: maxBackup,
MaxAge: maxAge,
}
return zapcore.AddSync(lumberJackLogger)
}
å
·ä½æ¥éª¤äºï¼Encoder:ç¼ç å¨(å¦ä½åå
¥æ¥å¿)
使ç¨å¼ç®±å³ç¨çNewJSONEncoder()
并使ç¨é¢å
设置çProductionEncoderConfig()
æ·»å ä¸äºå
¶ä»ä¿¡æ¯ï¼è¦çé»è®¤çï¼ï¼
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder // ä¿®æ¹æ¶é´ç¼ç å¨
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder// å¨æ¥å¿æ件ä¸ä½¿ç¨å¤§ååæ¯è®°å½æ¥å¿çº§å«
EncodeDurationï¼ä¸è¬zapcore.SecondsDurationEncoder,æ§è¡æ¶èçæ¶é´è½¬åææµ®ç¹åçç§
EncodeCallerï¼ä¸è¬zapcore.ShortCallerEncoderï¼ä»¥å
/æ件:è¡å· æ ¼å¼åè°ç¨å æ callerï¼å¯ä»¥ä»¥ç¸å¯¹æ ¼å¼shortåç»å¯¹æ ¼å¼fullæ¾ç¤º
TimeKeyï¼è¾åºæ¶é´çkeyå
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.TimeKey = "time"
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder
encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
return zapcore.NewJSONEncoder(encoderConfig)
}
- ä¸é¢ä¸¤è¡ä»£ç ç主è¦ä½ç¨æ¯ï¼è®¾ç½®æ¥å¿çº§å«
- 级å«æ¯æ¥å¿è®°å½çä¼å 级ï¼çº§å«è¶é«è¶éè¦ãå®ä¾ålevelï¼ç¶åè°ç¨å ¶UnmarshalText()æ¹æ³ï¼
var l = new(zapcore.Level)
err = l.UnmarshalText([]byte(cfg.Level))
if err != nil {
return
}
éè¿zapcore.NewCoreå建ä¸ä¸ªcoreï¼å°æ¥å¿åå
¥WriteSyncerã
zapcore.NewConsoleEncoder():å°æ¥å¿ä¿¡æ¯å¨æ§å¶å°æå°ï¼å°ç¼ç å¨ä»JSON Encoderæ´æ¹ä¸ºæ®éEncoderï¼
éè¿è°ç¨zap.NewProduction()/zap.NewDevelopment()æè
zap.Example()å建ä¸ä¸ªLoggerãå
¶ä¸çæ¯ä¸ä¸ªå½æ°é½å°å建ä¸ä¸ªloggerãå¯ä¸çåºå«å¨äºå®å°è®°å½çä¿¡æ¯ä¸åãNewDevelopmentï¼ï¼æ¹æ³æå°å
容æ´è¯¦ç»ã
zap.NewDevelopmentEncoderConfig()ï¼è¯¥æ¹æ³è¿åä¸ä¸ªåå§å好çzapcore.EncoderConfigï¼ç¼ç å¨ï¼
var core zapcore.Core
if mode == string(utils.ModeProd) {
// è¿å
¥ç产模å¼
core = zapcore.NewCore(encoder, writeSyncer, l)
} else {
// è¿å
¥å¼å模å¼ææµè¯æ¨¡å¼
consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
core = zapcore.NewTee(
zapcore.NewCore(encoder, writeSyncer, l),
zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stdout), l),
)
}
zap.New(â¦)æ¹æ³æ¥æå¨ä¼ éææé
ç½®æ¥å建æ¥å¿å®ä¾ func New(core zapcore.Core, options ...Option) *Logger
zap.AddCaller():æ·»å å°è°ç¨å½æ°ä¿¡æ¯è®°å½å°æ¥å¿ä¸çåè½
lg := zap.New(core, zap.AddCaller())
zap.ReplaceGlobals(lg) // æ¿æ¢zapå
ä¸å
¨å±çloggerå®ä¾ï¼åç»å¨å
¶ä»å
ä¸åªé使ç¨zap.L()è°ç¨å³å¯
return
Syncè°ç¨åºå±æ ¸å¿çSyncæ¹æ³ï¼å·æ°ä»»ä½ç¼å²çæ¥å¿æ¡ç®ãåºç¨ç¨åºå¨éåºä¹ååºè¯¥æ³¨æè°ç¨syncã
zap.L().Debug():è®°å½æ¥å¿
è¿éé¢è°ç¨äºutilséé¢çä¸ä¸ªæ¹æ³ã
defer zap.L().Sync()
zap.L().Debug(utils.Green("logger init success..."))
è¿å
¥utils.setTextæ件
å
çæ¹é声æçåéï¼constä¸æ¯æ°å¢ä¸è¡å¸¸é声æå°ä½¿iota计æ°ä¸æ¬¡
package utils
import (
"fmt"
)
// åæ¯ èæ¯ é¢è²
// ---------------------------------------
// 30 40 é»è²
// 31 41 红è²
// 32 42 绿è²
// 33 43 é»è²
// 34 44 èè²
// 35 45 紫红è²
// 36 46 éèè²
// 37 47 ç½è²
//
// 代ç æä¹
// -------------------------
// 0 ç»ç«¯é»è®¤è®¾ç½®
// 1 é«äº®æ¾ç¤º
// 4 使ç¨ä¸å线
// 5 éªç
// 7 åç½æ¾ç¤º
// 8 ä¸å¯è§
const (
TextBlack = iota + 30
TextRed
TextGreen
TextYellow
TextBlue
TextMagenta
TextCyan
TextWhite
)
func Black(msg string) string {
return SetColor(msg, 0, 0, TextBlack)
}
func Red(msg string) string {
return SetColor(msg, 0, 0, TextRed)
}
func Green(msg string) string {
return SetColor(msg, 0, 0, TextGreen)
}
func Yellow(msg string) string {
return SetColor(msg, 0, 0, TextYellow)
}
func Blue(msg string) string {
return SetColor(msg, 0, 0, TextBlue)
}
func Magenta(msg string) string {
return SetColor(msg, 0, 0, TextMagenta)
}
func Cyan(msg string) string {
return SetColor(msg, 0, 0, TextCyan)
}
func White(msg string) string {
return SetColor(msg, 0, 0, TextWhite)
}
func SetColor(msg string, conf, bg, text int) string {
return fmt.Sprintf("%c[%d;%d;%dm%s%c[0m", 0x1B, conf, bg, text, msg, 0x1B)
}
继ç»mainæ¹æ³ï¼
åå§åMySQLè¿æ¥
对äºmysql.Init()æ¹æ³ä¸é¢ä¼è¿è¡æåã
å
³éè¿æ¥è¿ä¸é¨åï¼
æ*gorm.DBæ¾å°ä¸ä¸ªå
Œ
±ç®å½ä¸ï¼åªééè¦åªéè°
// 3. åå§åMySQLè¿æ¥
if err := mysql.Init(config.MysqlConfig); err != nil {
zap.L().Error(fmt.Sprintf("init mysql failed, err:%v\n", err))
return
}
defer mysql.Close()
zap.L().Debug(utils.Green("mysql init success..."))
// Close å
³éè¿æ¥
func Close() {
db, err := global.Eloquent.DB()
if err != nil {
zap.L().Error("db close err", zap.Error(err))
}
_ = db.Close()
}
ä¼ å
¥çæ¯mysqlçé
置信æ¯ï¼ä½¿ç¨ä¸ä¸ªç»æä½åå¨
charset=utf8mb4ï¼è¿ç§å符ç¼ç æ¹å¼å¯ä»¥å¤ç表æ
å
parseTime=true&loc=Local说æä¼è§£ææ¶é´ï¼æ¶åºæ¯æºå¨çlocalæ¶åºãæºå¨ä¹é´çæ¶åºå¯è½ä¸ä¸è´ä¼è®¾ç½®æé®é¢ï¼è¿å¯¼è´ä»ç¸ååºçä¸åå®ä¾æ¥è¯¢åºæ¥çç»æå¯è½è§£æ以åå°±ä¸ä¸æ ·ãå æ¤æ¨èå°locç»ä¸è®¾ç½®ä¸ºä¸ä¸ªæ¶åº
timeout=1000msï¼è¿æ¥è¶
æ¶
å¨æ§å¶å°æå°æ示信æ¯
// Init é
ç½®mysql gorm
func Init(cfg *config.Mysql) (err error) {
source := fmt.Sprintf("%s:%[email protected](%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms",
cfg.User,
cfg.Password,
cfg.Host,
cfg.Port,
cfg.DbName,
)
zap.L().Info(utils.Green(source))
设置æ大è¿æ¥æ°åæ大空é²è¿æ¥æ°
db.SetMaxOpenConns(cfg.DbMaxOpen)
db.SetMaxIdleConns(cfg.DbMaxIdle)
ä¸é¢è¿ä¸æ³¢æä½ä½ç¨æ¯ï¼ä¸æ°æ®å»ºç«è¿æ¥
zap.L().xxx():xxx表示çæ¯æå°æ¥å¿ç级å«ï¼ä¸å级å«çæ¥å¿ä¿¡æ¯é¢è²ä¸åã
zap.L().Info(utils.Green(source))
db, err := sql.Open("mysql", source)
if err != nil {
zap.L().Fatal(utils.Red("mysql connect error :"), zap.Error(err))
return
}
db.SetMaxOpenConns(cfg.DbMaxOpen)
db.SetMaxIdleConns(cfg.DbMaxIdle)
global.Eloquent, err = open(db, &gorm.Config{
NamingStrategy: schema.NamingStrategy{
SingularTable: true,
},
})
if err != nil {
zap.L().Fatal(utils.Red("mysql connect error :"), zap.Error(err))
return
} else {
zap.L().Info(utils.Green("mysql connect success !"))
}
è°ç¨ä¸é¢çæ¹æ³ï¼è¿åä¸ä¸ªæ½è±¡çgormæ°æ®åºã
è¿æ¥æ°æ®åºæ¯è¾ç®åï¼ç´æ¥ä¼ å
¥å°åå³å¯ãä¸é¢è¿ç§æ¯è¾ä¸ºé«çº§çç¨æ³ï¼éè¿ä¸ä¸ªç°æçæ°æ®åºè¿æ¥æ¥åå§å *gorm.DB
GORM å
许ç¨æ·éè¿è¦çé»è®¤çNamingStrategyæ¥æ´æ¹å½å约å®ï¼è¿éè¦å®ç°1245/*--*æ¥å£ Namer
SingularTable: true, // 使ç¨åæ°è¡¨åï¼å¯ç¨è¯¥é项åï¼`User` 表å°æ¯`user`
// Open æå¼æ°æ®åºè¿æ¥
func open(db *sql.DB, cfg *gorm.Config) (*gorm.DB, error) {
return gorm.Open(mysql.New(mysql.Config{Conn: db}), cfg)
}
å¤æçæçè¿æ¥æ± æ¯å¦æé误
if global.Eloquent.Error != nil {
zap.L().Fatal(utils.Red(" database error :"), zap.Error(global.Eloquent.Error))
return
}
GORM å®ä¹ä¸ä¸ª gorm.Model ç»æä½ï¼å¯ä»¥å°å
¶åµå
¥å°æ¨çç»æä½ä¸ï¼ä»¥å
å«è¿å 个å段
AutoMigrate ç¨äºèªå¨è¿ç§»æ¨ç schemaï¼ä¿ææ¨ç schema æ¯ææ°çï¼æ ¹æ®æ¨¡å对象建表ï¼æ²¡æåå建ï¼ä¿®æ¹åèªå¨ä¿®æ¹ï¼
err = migrateModel()
if err != nil {
zap.L().Fatal(utils.Red(" migrateModel error :"), zap.Error(err))
}
return
// è¿ä¸¤é¨å代ç ä¸å¨ä¸ä¸ªæ件ä¸
func migrateModel() error {
err := orm.Eloquent.AutoMigrate(&models.SysUser{})
return err
}
package models
type SysUser struct {
*BaseModel
Username string `json:"username"`
Password string `json:"password"`
DeptId int `json:"dept_id"` //é¨é¨id
PostId int `json:"post_id"` //
RoleId int `json:"role_id"` //
NickName string `json:"nick_name"` //
Phone string `json:"phone"` //
Email string `json:"email"` //
AvatarPath string `json:"avatar_path"` //头åè·¯å¾
Avatar string `json:"avatar"` //
Sex string `json:"sex"` //
Status string `json:"status"` //
Remark string `json:"remark"` //
Salt string `json:"salt"` //
Gender []byte `json:"gender"` //æ§å«ï¼0为ç·é»è®¤ï¼1为女ï¼
IsAdmin []byte `json:"is_admin"` //æ¯å¦ä¸ºadminè´¦å·
Enabled []byte `json:"enabled"` //ç¶æï¼1å¯ç¨ï¼é»è®¤ï¼ã0ç¦ç¨
PwdResetTime int64 `json:"pwd_reset_time"` //ä¿®æ¹å¯ç çæ¶é´
CreateBy int `json:"create_by"` //
UpdateBy int `json:"update_by"` //
}
package models
// BaseModel ormå
¬æå段
type BaseModel struct {
ID int `gorm:"primary_key" json:"id"` //ID
IsDeleted []byte `gorm:"default:[]byte{0}" json:"is_deleted"` //é»è®¤ä¸ºé¶
CreateTime int64 `gorm:"autoCreateTime:milli" json:"create_time"` //å建æ¥æ é»è®¤å½åæ¶é´æ³ 毫ç§
UpdateTime int64 `gorm:"autoUpdateTime:milli" json:"update_time"` //æ´æ°æ¶é´ é»è®¤å½åæ¶é´æ³ 毫ç§
}
è³æ¤ï¼MySQLæ°æ®åºåå§åç»æï¼
ä¸é¢ä»£ç æ¯åå§åredisè¿æ¥
// 4. åå§åRedisè¿æ¥
if err := redis.Init(config.RedisConfig); err != nil {
zap.L().Error(fmt.Sprintf("init redis failed, err:%v\n", err))
return
}
defer redis.Close()
zap.L().Debug(utils.Green("redis init success..."))
éè¿ redis.NewClient å½æ°å³å¯å建ä¸ä¸ª redis 客æ·ç«¯
è¿ä¸ªæ¹æ³æ¥æ¶ä¸ä¸ª redis.Options 对象åæ°, éè¿è¿ä¸ªåæ°, æ们å¯ä»¥é ç½® redis ç¸å ³çå±æ§, ä¾å¦ redis æå¡å¨å°å, æ°æ®åºå, æ°æ®åºå¯ç ç.
éè¿ cient.Ping() æ¥æ£æ¥æ¯å¦æåè¿æ¥å°äº redis æå¡å¨
// Init åå§åredisè¿æ¥
func Init(cfg *config.Redis) (err error) {
global.Rdb = redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d",
cfg.Host,
cfg.Port,
),
Password: cfg.Password, // no password set
DB: cfg.DB, // use default DB
PoolSize: cfg.PoolSize,
IdleTimeout: time.Duration(cfg.IdleTimeOutSec),
})
_, err = global.Rdb.Ping().Result()
return
}
func Close() {
_ = global.Rdb.Close()
}
åå§åcasbin
//åå§åcasbin
if err := mycasbin.Setup(); err != nil {
zap.L().Error("casbin failed set up", zap.Error(err))
}
gormadapter.NewAdapterByDB()ï¼ // å°æ°æ®åºè¿æ¥åæ¥ç»æä»¶ï¼ æ件ç¨æ¥æä½æ°æ®åºï¼çæmySQLéé å¨
âå¯ä»¥å å°å符串解æ为Model对象ï¼ç¶ååå建Enforcerï¼
enforcer, err = casbin.NewSyncedEnforcer(m)ï¼ // å¨å¤çº¿ç¨ç¯å¢ä¸ä½¿ç¨Enforcer对象çæ¥å£ï¼å¿ 须使ç¨casbin.NewSyncedEnforcerå建Enforcer
casbinç®è¿°ï¼
âModelåå¨ï¼
ââå¨ Casbin ä¸, 访é®æ§å¶æ¨¡å被æ½è±¡ä¸ºåºäº PERM (Policy, Effect, Request, Matcher) çä¸ä¸ªæ件
ââModelè¯æ³ï¼
âââRequestå®ä¹ï¼[requset_definition]é¨åç¨äºrequestçå®ä¹ï¼subï¼è®¿é®å®ä½ï¼subjectï¼,objï¼è®¿é®èµæºï¼objectï¼å访é®æ¹æ³ï¼Actionï¼
âââPolicytå®ä¹ï¼å¯¹policyçå®ä¹ï¼policyé¨åçæ¯ä¸è¡ç§°ä¹ä¸ºä¸ä¸ªçç¥è§å
âââmatcherså®ä¹ï¼å®ä¹äºçç¥å¹é è ãå¹é è æ¯ä¸ç»è¡¨è¾¾å¼ãå®å®ä¹äºå¦ä½æ ¹æ®è¯·æ±æ¥å¹é çç¥è§å
ââä¸policyä¸åï¼modelåªè½å è½½ï¼ä¸è½ä¿åï¼å¦ä¸å¾çtextï¼
âââ使ç¨å 载模åï¼è¿é使ç¨ä»å符串ä¸å è½½modelï¼ï¼model.NewModelFromStringï¼ï¼ï¼ //å¯ä»¥ä»å¤è¡å符串å è½½æ´ä¸ªæ¨¡åææ¬ãè¿ç§æ¹æ³çä¼ç¹æ¯æ¨ä¸éè¦ç»´æ¤æ¨¡åæ件ã
// Initialize the model from a string.
var text = `
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = r.sub == p.sub && (keyMatch2(r.obj, p.obj) || keyMatch(r.obj, p.obj)) && (r.act == p.act || p.act == "*")
`
func Setup() (err error) {
//var err error
var Apter *gormAdapter.Adapter
var m model.Model
var e *casbin.SyncedEnforcer
Apter, err = gormAdapter.NewAdapterByDB(global.Eloquent)
if err != nil {
zap.L().Error("NewAdapterByDB()", zap.Error(err))
return err
}
m, err = model.NewModelFromString(text)
if err != nil {
zap.L().Error("NewModelFromString()", zap.Error(err))
return err
}
e, err = casbin.NewSyncedEnforcer(m, Apter)
if err != nil {
zap.L().Error("NewSyncedEnforcer()", zap.Error(err))
return err
}
global.CasbinEnforcer = e
return nil
}