1 Star 0 Fork 0

tomatomeatman/GolangRepository

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
AppUtil.go 7.52 KB
一键复制 编辑 原始数据 按行查看 历史
tomatomeatman 提交于 2025-02-26 17:57 +08:00 . 2
package app
import (
"fmt"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"sync"
"time"
"gitee.com/tomatomeatman/golang-repository/bricks2/function/data/aesutil"
"gitee.com/tomatomeatman/golang-repository/bricks2/model/msgentity"
Log "github.com/cihub/seelog"
"github.com/fsnotify/fsnotify"
"gopkg.in/ini.v1"
)
var (
glbAppiCloudApp = 0 //是否要加入分布式系统(0:待初始化;1:是;2:否)
glbAppiCloudSystem = 0 // 判断程序是否启用桥接
configData = map[string]map[string]*ini.Key{} //配置文件配置项
watchOnce sync.Once //监听文件变化单例
)
// type AppUtil struct{}
// 判断程序是否要加入分布式系统
func IsCloudApp() bool {
if glbAppiCloudApp != 0 {
return glbAppiCloudApp == 1
}
if HasSection("CloudCenter") {
glbAppiCloudApp = 1
return true
}
glbAppiCloudApp = 2
return false
}
// 判断程序是否非分布式系统
func IsNotCloudApp() bool {
return !IsCloudApp()
}
// 判断程序是否启用桥接
func IsCloudSystem() bool {
if glbAppiCloudSystem != 0 {
return glbAppiCloudSystem == 1
}
if HasSection("CloudSystem") {
glbAppiCloudSystem = 1
return true
}
glbAppiCloudSystem = 2
return false
}
// 判断程序是否禁用桥接
func IsNotCloudSystem() bool {
return !IsCloudSystem()
}
// 判断配置组是否存在
func HasSection(sectionName string) bool {
iniCfg()
section, ok := configData[sectionName]
if !ok || section == nil || len(section) == 0 {
return false
}
return len(section) > 0
}
// 读取配置值
func ReadConfigKey(section, key string, def interface{}) interface{} {
iniCfg()
keys, ok := configData[section]
if !ok || keys == nil {
return def
}
value, ok := keys[key]
if !ok {
return def
}
if value == nil {
return def
}
if def == nil {
def = ""
}
isEncrypt := false
temp := fmt.Sprintf("%v", value)
if strings.HasPrefix(temp, "${") && strings.HasSuffix(temp, "}") {
isEncrypt = true
temp = aesutil.Decrypt(temp[2:len(temp)-1], "bricks")
}
switch def.(type) {
case string: // 将interface转为string字符串类型
if isEncrypt {
return temp
}
return value.String()
case int:
if isEncrypt {
result, err := strconv.Atoi(temp)
if err != nil {
return def
}
return result
}
result, err := value.Int()
if err != nil {
return def
}
return result
case int64:
if isEncrypt {
result, err := strconv.ParseInt(temp, 10, 64)
if err != nil {
return def
}
return result
}
result, err := value.Int64()
if err != nil {
return def
}
return result
case float64:
if isEncrypt {
result, err := strconv.ParseFloat(temp, 64)
if err != nil {
return def
}
return result
}
result, err := value.Float64()
if err != nil {
return def
}
return result
case bool:
if isEncrypt {
result, err := strconv.ParseBool(temp) //接受 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False 等字符串;
if err != nil {
return def
}
return result
}
result, err := value.Bool()
if err != nil {
return def
}
return result
default:
return value.String()
}
}
// 初始化配置文件变量
func iniCfg() {
if len(configData) > 0 {
return //已经读取
}
root := ""
exePath, err := os.Executable()
if err != nil {
root = "."
}
root, _ = filepath.EvalSymlinks(filepath.Dir(exePath))
configFilePath := strings.Replace(root+"/config/app.ini", "\\", "/", -1)
_, err = os.Stat(configFilePath) //os.Stat获取文件信息
if err != nil {
if !os.IsExist(err) {
Log.Error("配置文件不存在", err)
return
}
}
appCfg, err := ini.Load(configFilePath)
if err != nil {
Log.Error("配置文件读取错误", err)
return
}
sections := appCfg.Sections()
for _, section := range sections {
keys := make(map[string]*ini.Key)
for _, key := range section.Keys() {
keys[key.Name()] = key
}
configData[section.Name()] = keys
}
watchOnce.Do(func() {
go watchConfigFile(configFilePath) //监听文件变化
})
}
/**
* 通过结构体获取
* @param entity 结构体样式
* @param names 辅助'项名称',若不传递则按结构体名称做'项名称'
* @return 返回新建结构体实体
*/
func ToEntity(entity interface{}, names ...string) *msgentity.MsgEntity {
if entity == nil {
entity = map[string]interface{}{}
}
iniCfg()
rt := reflect.TypeOf(entity)
rve := reflect.New(rt).Elem()
if len(names) < 1 {
Name := rt.Name()
if strings.Contains(Name, "map[string]") || strings.HasPrefix(Name, "[]") {
return msgentity.Err(1002, "不明确的配置项,无法进行解析")
}
names = append(names, Name)
}
for _, Name := range names {
section, ok := configData[Name]
if !ok || section == nil {
continue
}
for k := 0; k < rt.NumField(); k++ {
value, ok := section[rt.Field(k).Name]
if !ok || value == nil {
continue
}
field := rve.FieldByName(rt.Field(k).Name)
if !field.IsValid() {
continue
}
{
temp := value.String()
if strings.Contains(temp, "${") {
continue //配置中含有变量符,不获取(待改进)
}
}
switch field.Type().String() {
case "string":
field.Set(reflect.ValueOf(value.String()))
case "int":
temp, err := value.Int()
if err != nil {
continue
}
field.Set(reflect.ValueOf(temp))
case "int64":
temp, err := value.Int64()
if err != nil {
continue
}
field.Set(reflect.ValueOf(temp))
case "bool":
temp, err := value.Bool()
if err != nil {
continue
}
field.Set(reflect.ValueOf(temp))
case "float64":
temp, err := value.Float64()
if err != nil {
continue
}
field.Set(reflect.ValueOf(temp))
default:
field.Set(reflect.ValueOf(value.String()))
}
}
}
result := rve.Interface()
return msgentity.Success(result, "转换结束")
}
/**
* 释放配置文件
*/
func FreeappCfg() {
configData = make(map[string]map[string]*ini.Key)
}
// 使用 fsnotify 监听配置文件的变化,注意调用watchConfigFile时必须使用go watchConfigFile(),否则会造成阻塞
func watchConfigFile(filePath string) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
Log.Error("开启配置文件监听失败", err)
}
defer watcher.Close()
if err := watcher.Add(filePath); err != nil {
Log.Error("添加配置文件到监听器发生异常:", err)
}
var lastModTime time.Time
fileInfo, err := os.Stat(filePath)
if err == nil {
lastModTime = fileInfo.ModTime()
}
// done := make(chan bool)
func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Op&fsnotify.Write == fsnotify.Write {
// 检查文件的最后修改时间是否发生变化
fileInfo, err := os.Stat(filePath)
if err != nil {
Log.Error("获取文件修改时间失败:", err)
continue
}
if fileInfo.ModTime().After(lastModTime) {
lastModTime = fileInfo.ModTime()
Log.Error("配置文件被修改,即将重新加载")
FreeappCfg() //释放配置信息
iniCfg() //重新初始化配置信息
}
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
Log.Error("监听配置文件时发生异常:", err)
}
}
}()
// <-done // 阻塞,让调用watchConfigFile的线程进入阻塞状态
}
// 获取当前执行程序所在的绝对路径
func AppPath() string {
exePath, err := os.Executable()
if err != nil {
return "./"
}
res, _ := filepath.EvalSymlinks(filepath.Dir(exePath))
return res
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/tomatomeatman/golang-repository.git
git@gitee.com:tomatomeatman/golang-repository.git
tomatomeatman
golang-repository
GolangRepository
61e401b0d628

搜索帮助