1.读取配置文件
_serverConfig, err := goconfig.LoadConfigFile("./conf/config.conf") if err != nil { Log.Error("read config.ini error:", err.Error()) }
_serverConfig.MustValue(section, key, defaultVal...)
2.数据库初始化
preFix := "my_" + configs.FACTORY dbhost = configs.GetServerProp(preFix, "dbhost", "") dbport = configs.GetServerProp(preFix, "dbport", "") dbname = configs.GetServerProp(preFix, "dbname", "") username = configs.GetServerProp(preFix, "username", "") passwd = configs.GetServerProp(preFix, "passwd", "") sslmode = configs.GetServerProp(preFix, "sslmode", "") schema = configs.GetServerProp(preFix, "schema", "") urlTb := utils.Sprintf("host=%v port=%v user=%v password=%v dbname=%v sslmode=%v search_path=%v", dbhost, dbport, username, passwd, dbname, sslmode, schema) database, err := sql.Open("postgres", urlTb) if err != nil { configs.Log.Error("open postgre failed, err:", err.Error()) return } database.SetConnMaxLifetime(configs.DB_TIMEOUT_DURATION) database.SetMaxOpenConns(50) database.SetMaxIdleConns(5) Dbmy := database
3.数据库查询
func SelectBySql(myDb *sql.DB, execSql string, args ...any) ([]map[string]string, error) { defer func() { if er := recover(); er != nil { erLog := utils.Sprintf("%v panic:%v", utils.RunFuncName(), er) configs.Log.Error(erLog) } }() resArray := []map[string]string{} //增加contxt ctx, cancel := context.WithTimeout(context.Background(), configs.DB_TIMEOUT_DURATION) defer cancel() var rows *sql.Rows var err error if nil != args && len(args) > 0 { rows, err = myDb.QueryContext(ctx, execSql, args...) } else { rows, err = myDb.QueryContext(ctx, execSql) } if nil != err { return resArray, err } defer rows.Close() cols, err := rows.Columns() if err != nil { return resArray, err } colSize := len(cols) record := make([]any, colSize) container := make([]sql.NullString, colSize) for i := 0; i < colSize; i++ { record[i] = &container[i] } row := make(map[string]string) for rows.Next() { err = rows.Scan(record...) if nil != err { return resArray, err } row = make(map[string]string) for i, column := range cols { if container[i].Valid { row[strings.ToUpper(column)] = strings.Replace(container[i].String, "\u0000", "", -1) } else { row[strings.ToUpper(column)] = "" } } resArray = append(resArray, row) row = nil } record = nil container = nil return resArray, nil }
4.数据库插入或者修改
ctx, cancel := context.WithTimeout(context.Background(), configs.DB_TIMEOUT_DURATION) defer cancel() tx, errBegin := myDb.BeginTx(ctx, nil) if nil != errBegin { configs.Log.Error("err:", errBegin.Error()) return errBegin } for _, execSql := range execSqls { _, errExec := tx.ExecContext(ctx, execSql) if nil != errExec { configs.Log.Error("err:", errExec.Error()) return errExec } } return tx.Commit()
5.日志自动保存
var ( pointArr model.SafeArray[string] // lastWriteOn time.Time = time.Now() ) func init() { pointArr.SetAll(make([]string, configs.INFLUX_BATCH)) } func Write(execsql string) { if nil == DbSourceTb { return } currArrLen := pointArr.Push(execsql) // if currArrLen >= configs.INFLUX_BATCH { execSqls := pointArr.PopAndClean(configs.INFLUX_BATCH) for i := 0; i < configs.RETRY_COUNT; i++ { err := ExecBatchBarcodeD7x(execSqls) if nil == err { break } } execSqls = nil lastWriteOn = time.Now() } execsql = "" } func AutoWriterAfterTime() { defer func() { if er := recover(); er != nil { erLog := utils.Sprintf("AutoWriterAfterTime panic: %v", er) configs.Log.Error(erLog) } }() if nil == DbSourceTb { return } currArrLen := pointArr.NowIndex() // if currArrLen > 0 && time.Now().Sub(lastWriteOn).Milliseconds() >= 30000 { execSqls := pointArr.PopAndClean(configs.INFLUX_BATCH) for i := 0; i < configs.RETRY_COUNT; i++ { err := ExecBatchBarcodeD7x(execSqls) if nil == err { break } } execSqls = nil lastWriteOn = time.Now() } } func ExecBatchBarcodeD7x(barcodes []string) (err error) { var sqlSb strings.Builder defer func() { if er := recover(); er != nil { erLog := utils.Sprintf("%v panic:%v", utils.RunFuncName(), er) err = errors.New(erLog) configs.Log.Error(erLog) } }() i := 0 for _, v := range barcodes { sqlSb.WriteString(";") sqlSb.WriteString(v) i++ if i > configs.DB_BATCH_COMMIT_SIZE { sqls := sqlSb.String() err = ExecCommit(sqls, true) if err != nil { err = SingleSqlCommit(sqls) if nil != err { configs.Log.Error("single sql error", err) sqls = "" barcodes = nil sqlSb.Reset() return err } } i = 0 sqls = "" sqlSb.Reset() } } // sqls := sqlSb.String() sqlSb.Reset() if sqls != "" { err = ExecCommit(sqls, true) if err != nil { err = SingleSqlCommit(sqls) if nil != err { sqls = "" barcodes = nil sqlSb.Reset() configs.Log.Error("single sql error", err) return err } } } sqls = "" barcodes = nil return nil } func ExecCommit(sqls string, isBatch bool) error { defer func() { if er := recover(); er != nil { erLog := utils.Sprintf("%v panic:%v", utils.RunFuncName(), er) configs.Log.Error(erLog) } }() timeOut := 3 * time.Second if isBatch { timeOut = 12 * time.Second } ctx, cancel := context.WithTimeout(context.Background(), timeOut) defer cancel() tx, err := DbSourceTb.BeginTx(ctx, nil) if err != nil { sqls = "" return err } _, err = tx.ExecContext(ctx, sqls) if err != nil { _ = tx.Rollback() sqls = "" return err } sqls = "" return tx.Commit() } func SingleSqlCommit(sqls string) (err error) { defer func() { if er := recover(); er != nil { erLog := utils.Sprintf("%v panic:%v, execsql:%s", utils.RunFuncName(), er, sqls) err = errors.New(erLog) configs.Log.Error(erLog) } }() insqls := strings.Split(sqls, ";") for _, v := range insqls { if len(v) > 5 { err = ExecCommit(v, false) } } sqls = "" insqls = nil return nil }
6.中间件
type bodyLogWriter struct { gin.ResponseWriter body *bytes.Buffer } //json func (w bodyLogWriter) Write(b []byte) (int, error) { return w.body.Write(b) } // func (w bodyLogWriter) WriteString(s string) (int, error) { return w.body.WriteString(s) }
func FuckLogger() gin.HandlerFunc {
return func(ctx *gin.Context) {
defer func() {
if err := recover(); err != nil {
configs.Log.Error(err)
}
}()
bodyLogWrit := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: ctx.Writer}
ctx.Writer = bodyLogWrit
var reqStr string
var resStr string
var costTime int64
startTime := time.Now()
requestPath := ctx.Request.URL.Path
//开始时间
defer func() {
if err := recover(); err != nil {
resStr, _ = sjson.Set(resStr, "rc", model.API_RESULT_RC_ERR)
resStr, _ = sjson.Set(resStr, "rm", utils.Sprintf("request [%v] error:%v", requestPath, err))
}
//
resStr, _ = sjson.Set(resStr, "sysDate", time.Now().Format(model.DATE_TIME_FORMAT_SYSDATE))
costTime = time.Since(startTime).Milliseconds()
resStr, _ = sjson.Set(resStr, "csTime", utils.Sprintf("%dms", costTime))
ctx.Writer = bodyLogWrit.ResponseWriter
ctx.String(http.StatusOK, resStr)
//log
}()
//拦截代码
reqData, _ := io.ReadAll(ctx.Request.Body)
defer ctx.Request.Body.Close()
ctx.Request.Body = io.NopCloser(bytes.NewBuffer(reqData)) //
reqStr = string(reqData)
//next
ctx.Next()
resStr = string(bodyLogWrit.body.Bytes())
}
}
//gin使用
gin.SetMode(gin.ReleaseMode)