mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
refract pacakge gcfg, adding adapter interface for pacakge gcfg
This commit is contained in:
@ -12,31 +12,31 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// instances is the instance map for common used components.
|
||||
instances = gmap.NewStrAnyMap(true)
|
||||
// localInstances is the instance map for common used components.
|
||||
localInstances = gmap.NewStrAnyMap(true)
|
||||
)
|
||||
|
||||
// Get returns the instance by given name.
|
||||
func Get(name string) interface{} {
|
||||
return instances.Get(name)
|
||||
return localInstances.Get(name)
|
||||
}
|
||||
|
||||
// Set sets a instance object to the instance manager with given name.
|
||||
func Set(name string, instance interface{}) {
|
||||
instances.Set(name, instance)
|
||||
localInstances.Set(name, instance)
|
||||
}
|
||||
|
||||
// GetOrSet returns the instance by name,
|
||||
// or set instance to the instance manager if it does not exist and returns this instance.
|
||||
func GetOrSet(name string, instance interface{}) interface{} {
|
||||
return instances.GetOrSet(name, instance)
|
||||
return localInstances.GetOrSet(name, instance)
|
||||
}
|
||||
|
||||
// GetOrSetFunc returns the instance by name,
|
||||
// or sets instance with returned value of callback function `f` if it does not exist
|
||||
// and then returns this instance.
|
||||
func GetOrSetFunc(name string, f func() interface{}) interface{} {
|
||||
return instances.GetOrSetFunc(name, f)
|
||||
return localInstances.GetOrSetFunc(name, f)
|
||||
}
|
||||
|
||||
// GetOrSetFuncLock returns the instance by name,
|
||||
@ -46,11 +46,11 @@ func GetOrSetFunc(name string, f func() interface{}) interface{} {
|
||||
// GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function `f`
|
||||
// with mutex.Lock of the hash map.
|
||||
func GetOrSetFuncLock(name string, f func() interface{}) interface{} {
|
||||
return instances.GetOrSetFuncLock(name, f)
|
||||
return localInstances.GetOrSetFuncLock(name, f)
|
||||
}
|
||||
|
||||
// SetIfNotExist sets <instance> to the map if the `name` does not exist, then returns true.
|
||||
// It returns false if <name> exists, and `instance` would be ignored.
|
||||
func SetIfNotExist(name string, instance interface{}) bool {
|
||||
return instances.SetIfNotExist(name, instance)
|
||||
return localInstances.SetIfNotExist(name, instance)
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/os/gcfg"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
|
||||
@ -25,59 +26,79 @@ const (
|
||||
configNodeNameDatabase = "database"
|
||||
)
|
||||
|
||||
// Database returns an instance of database ORM object
|
||||
// with specified configuration group name.
|
||||
// Database returns an instance of database ORM object with specified configuration group name.
|
||||
// Note that it panics if any error occurs duration instance creating.
|
||||
func Database(name ...string) gdb.DB {
|
||||
group := gdb.DefaultGroupName
|
||||
var (
|
||||
ctx = context.Background()
|
||||
group = gdb.DefaultGroupName
|
||||
)
|
||||
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
group = name[0]
|
||||
}
|
||||
instanceKey := fmt.Sprintf("%s.%s", frameCoreComponentNameDatabase, group)
|
||||
db := instances.GetOrSetFuncLock(instanceKey, func() interface{} {
|
||||
db := localInstances.GetOrSetFuncLock(instanceKey, func() interface{} {
|
||||
// It ignores returned error to avoid file no found error while it's not necessary.
|
||||
var (
|
||||
configMap map[string]interface{}
|
||||
configNodeKey string
|
||||
configNodeKey = configNodeNameDatabase
|
||||
)
|
||||
// It firstly searches the configuration of the instance name.
|
||||
if Config().Available() {
|
||||
configNodeKey, _ = gutil.MapPossibleItemByKey(
|
||||
Config().GetMap("."),
|
||||
configNodeNameDatabase,
|
||||
)
|
||||
if configNodeKey == "" {
|
||||
configNodeKey = configNodeNameDatabase
|
||||
if configData, _ := Config().Data(ctx); len(configData) > 0 {
|
||||
if v, _ := gutil.MapPossibleItemByKey(configData, configNodeNameDatabase); v != "" {
|
||||
configNodeKey = v
|
||||
}
|
||||
configMap = Config().GetMap(configNodeKey)
|
||||
}
|
||||
if v, _ := Config().Get(ctx, configNodeKey); !v.IsEmpty() {
|
||||
configMap = v.Map()
|
||||
}
|
||||
if len(configMap) == 0 && !gdb.IsConfigured() {
|
||||
configFilePath, _ := Config().GetFilePath()
|
||||
if configFilePath == "" {
|
||||
exampleFileName := "config.example.toml"
|
||||
if exampleConfigFilePath, _ := Config().GetFilePath(exampleFileName); exampleConfigFilePath != "" {
|
||||
panic(gerror.NewCodef(
|
||||
gcode.CodeMissingConfiguration,
|
||||
`configuration file "%s" not found, but found "%s", did you miss renaming the example configuration file?`,
|
||||
Config().GetFileName(),
|
||||
exampleFileName,
|
||||
))
|
||||
} else {
|
||||
panic(gerror.NewCodef(
|
||||
gcode.CodeMissingConfiguration,
|
||||
`configuration file "%s" not found, did you miss the configuration file or the misspell the configuration file name?`,
|
||||
Config().GetFileName(),
|
||||
))
|
||||
// File configuration object checks.
|
||||
var (
|
||||
err error
|
||||
configFilePath string
|
||||
)
|
||||
if fileConfig, ok := Config().GetAdapter().(*gcfg.AdapterFile); ok {
|
||||
if configFilePath, err = fileConfig.GetFilePath(); configFilePath == "" {
|
||||
exampleFileName := "config.example.toml"
|
||||
if exampleConfigFilePath, _ := fileConfig.GetFilePath(exampleFileName); exampleConfigFilePath != "" {
|
||||
err = gerror.WrapCodef(
|
||||
gcode.CodeMissingConfiguration,
|
||||
err,
|
||||
`configuration file "%s" not found, but found "%s", did you miss renaming the example configuration file?`,
|
||||
fileConfig.GetFileName(),
|
||||
exampleFileName,
|
||||
)
|
||||
} else {
|
||||
err = gerror.WrapCodef(
|
||||
gcode.CodeMissingConfiguration,
|
||||
err,
|
||||
`configuration file "%s" not found, did you miss the configuration file or the misspell the configuration file name?`,
|
||||
fileConfig.GetFileName(),
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
panic(gerror.NewCodef(
|
||||
gcode.CodeMissingConfiguration,
|
||||
`database initialization failed: "%s" node not found, is configuration file or configuration node missing?`,
|
||||
configNodeNameDatabase,
|
||||
))
|
||||
// Panic if nothing found in Config object or in gdb configuration.
|
||||
if len(configMap) == 0 && !gdb.IsConfigured() {
|
||||
err = gerror.WrapCodef(
|
||||
gcode.CodeMissingConfiguration,
|
||||
err,
|
||||
`database initialization failed: "%s" node not found, is configuration file or configuration node missing?`,
|
||||
configNodeNameDatabase,
|
||||
)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(configMap) == 0 {
|
||||
configMap = make(map[string]interface{})
|
||||
}
|
||||
// Parse `m` as map-slice and adds it to gdb's global configurations.
|
||||
// Parse `m` as map-slice and adds it to global configurations for package gdb.
|
||||
for g, groupConfig := range configMap {
|
||||
cg := gdb.ConfigGroup{}
|
||||
switch value := groupConfig.(type) {
|
||||
@ -94,11 +115,11 @@ func Database(name ...string) gdb.DB {
|
||||
}
|
||||
if len(cg) > 0 {
|
||||
if gdb.GetConfig(group) == nil {
|
||||
intlog.Printf(context.TODO(), "add configuration for group: %s, %#v", g, cg)
|
||||
intlog.Printf(ctx, "add configuration for group: %s, %#v", g, cg)
|
||||
gdb.SetConfigGroup(g, cg)
|
||||
} else {
|
||||
intlog.Printf(context.TODO(), "ignore configuration as it already exists for group: %s, %#v", g, cg)
|
||||
intlog.Printf(context.TODO(), "%s, %#v", g, cg)
|
||||
intlog.Printf(ctx, "ignore configuration as it already exists for group: %s, %#v", g, cg)
|
||||
intlog.Printf(ctx, "%s, %#v", g, cg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -112,27 +133,33 @@ func Database(name ...string) gdb.DB {
|
||||
|
||||
if len(cg) > 0 {
|
||||
if gdb.GetConfig(group) == nil {
|
||||
intlog.Printf(context.TODO(), "add configuration for group: %s, %#v", gdb.DefaultGroupName, cg)
|
||||
intlog.Printf(ctx, "add configuration for group: %s, %#v", gdb.DefaultGroupName, cg)
|
||||
gdb.SetConfigGroup(gdb.DefaultGroupName, cg)
|
||||
} else {
|
||||
intlog.Printf(context.TODO(), "ignore configuration as it already exists for group: %s, %#v", gdb.DefaultGroupName, cg)
|
||||
intlog.Printf(context.TODO(), "%s, %#v", gdb.DefaultGroupName, cg)
|
||||
intlog.Printf(ctx, "ignore configuration as it already exists for group: %s, %#v", gdb.DefaultGroupName, cg)
|
||||
intlog.Printf(ctx, "%s, %#v", gdb.DefaultGroupName, cg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new ORM object with given configurations.
|
||||
if db, err := gdb.New(name...); err == nil {
|
||||
if Config().Available() {
|
||||
// Initialize logger for ORM.
|
||||
var loggerConfigMap map[string]interface{}
|
||||
loggerConfigMap = Config().GetMap(fmt.Sprintf("%s.%s", configNodeKey, configNodeNameLogger))
|
||||
if len(loggerConfigMap) == 0 {
|
||||
loggerConfigMap = Config().GetMap(configNodeKey)
|
||||
// Initialize logger for ORM.
|
||||
var (
|
||||
loggerConfigMap map[string]interface{}
|
||||
loggerNodeName = fmt.Sprintf("%s.%s", configNodeKey, configNodeNameLogger)
|
||||
)
|
||||
if v, _ := Config().Get(ctx, loggerNodeName); !v.IsEmpty() {
|
||||
loggerConfigMap = v.Map()
|
||||
}
|
||||
if len(loggerConfigMap) == 0 {
|
||||
if v, _ := Config().Get(ctx, configNodeKey); !v.IsEmpty() {
|
||||
loggerConfigMap = v.Map()
|
||||
}
|
||||
if len(loggerConfigMap) > 0 {
|
||||
if err := db.GetLogger().SetConfigWithMap(loggerConfigMap); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
if len(loggerConfigMap) > 0 {
|
||||
if err = db.GetLogger().SetConfigWithMap(loggerConfigMap); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return db
|
||||
@ -158,7 +185,7 @@ func parseDBConfigNode(value interface{}) *gdb.ConfigNode {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// To be compatible with old version.
|
||||
// Be compatible with old version.
|
||||
if _, v := gutil.MapPossibleItemByKey(nodeMap, "LinkInfo"); v != nil {
|
||||
node.Link = gconv.String(v)
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package gins
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
@ -19,29 +20,44 @@ const (
|
||||
|
||||
// Log returns an instance of glog.Logger.
|
||||
// The parameter `name` is the name for the instance.
|
||||
// Note that it panics if any error occurs duration instance creating.
|
||||
func Log(name ...string) *glog.Logger {
|
||||
instanceName := glog.DefaultName
|
||||
var (
|
||||
ctx = context.Background()
|
||||
instanceName = glog.DefaultName
|
||||
)
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
instanceName = name[0]
|
||||
}
|
||||
instanceKey := fmt.Sprintf("%s.%s", frameCoreComponentNameLogger, instanceName)
|
||||
return instances.GetOrSetFuncLock(instanceKey, func() interface{} {
|
||||
return localInstances.GetOrSetFuncLock(instanceKey, func() interface{} {
|
||||
logger := glog.Instance(instanceName)
|
||||
// To avoid file no found error while it's not necessary.
|
||||
if Config().Available() {
|
||||
var m map[string]interface{}
|
||||
nodeKey, _ := gutil.MapPossibleItemByKey(Config().GetMap("."), configNodeNameLogger)
|
||||
if nodeKey == "" {
|
||||
nodeKey = configNodeNameLogger
|
||||
var (
|
||||
configMap map[string]interface{}
|
||||
loggerNodeName = configNodeNameLogger
|
||||
)
|
||||
// Try to find possible `loggerNodeName` in case-insensitive way.
|
||||
if configData, _ := Config().Data(ctx); len(configData) > 0 {
|
||||
if v, _ := gutil.MapPossibleItemByKey(configData, configNodeNameLogger); v != "" {
|
||||
loggerNodeName = v
|
||||
}
|
||||
m = Config().GetMap(fmt.Sprintf(`%s.%s`, nodeKey, instanceName))
|
||||
if len(m) == 0 {
|
||||
m = Config().GetMap(nodeKey)
|
||||
}
|
||||
// Retrieve certain logger configuration by logger name.
|
||||
certainLoggerNodeName := fmt.Sprintf(`%s.%s`, loggerNodeName, instanceName)
|
||||
if v, _ := Config().Get(ctx, certainLoggerNodeName); !v.IsEmpty() {
|
||||
configMap = v.Map()
|
||||
}
|
||||
// Retrieve global logger configuration if configuration for certain logger name does not exist.
|
||||
if len(configMap) == 0 {
|
||||
if v, _ := Config().Get(ctx, loggerNodeName); !v.IsEmpty() {
|
||||
configMap = v.Map()
|
||||
}
|
||||
if len(m) > 0 {
|
||||
if err := logger.SetConfigWithMap(m); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
// Set logger config if config map is not empty.
|
||||
if len(configMap) > 0 {
|
||||
if err := logger.SetConfigWithMap(configMap); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return logger
|
||||
|
||||
@ -7,8 +7,11 @@
|
||||
package gins
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/database/gredis"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
)
|
||||
@ -19,42 +22,46 @@ const (
|
||||
)
|
||||
|
||||
// Redis returns an instance of redis client with specified configuration group name.
|
||||
// Note that it panics if any error occurs duration instance creating.
|
||||
func Redis(name ...string) *gredis.Redis {
|
||||
config := Config()
|
||||
group := gredis.DefaultGroupName
|
||||
var (
|
||||
ctx = context.Background()
|
||||
group = gredis.DefaultGroupName
|
||||
)
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
group = name[0]
|
||||
}
|
||||
instanceKey := fmt.Sprintf("%s.%s", frameCoreComponentNameRedis, group)
|
||||
result := instances.GetOrSetFuncLock(instanceKey, func() interface{} {
|
||||
result := localInstances.GetOrSetFuncLock(instanceKey, func() interface{} {
|
||||
// If already configured, it returns the redis instance.
|
||||
if _, ok := gredis.GetConfig(group); ok {
|
||||
return gredis.Instance(group)
|
||||
}
|
||||
// Or else, it parses the default configuration file and returns a new redis instance.
|
||||
var m map[string]interface{}
|
||||
if _, v := gutil.MapPossibleItemByKey(Config().GetMap("."), configNodeNameRedis); v != nil {
|
||||
m = gconv.Map(v)
|
||||
var (
|
||||
configMap map[string]interface{}
|
||||
)
|
||||
|
||||
if configData, err := Config().Data(ctx); err != nil {
|
||||
panic(gerror.WrapCode(gcode.CodeOperationFailed, err, `retrieving redis configuration failed`))
|
||||
} else {
|
||||
if _, v := gutil.MapPossibleItemByKey(configData, configNodeNameRedis); v != nil {
|
||||
configMap = gconv.Map(v)
|
||||
}
|
||||
}
|
||||
if len(m) > 0 {
|
||||
if v, ok := m[group]; ok {
|
||||
|
||||
if len(configMap) > 0 {
|
||||
if v, ok := configMap[group]; ok {
|
||||
redisConfig, err := gredis.ConfigFromStr(gconv.String(v))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return gredis.New(redisConfig)
|
||||
} else {
|
||||
panic(fmt.Sprintf(`configuration for redis not found for group "%s"`, group))
|
||||
panic(fmt.Sprintf(`missing configuration for redis group "%s"`, group))
|
||||
}
|
||||
} else {
|
||||
filepath, err := config.GetFilePath()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
panic(fmt.Sprintf(
|
||||
`incomplete configuration for redis: "redis" node not found in config file "%s"`,
|
||||
filepath,
|
||||
))
|
||||
panic(`missing configuration for redis: "redis" node not found`)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
@ -7,8 +7,11 @@
|
||||
package gins
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/net/ghttp"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
)
|
||||
|
||||
@ -18,43 +21,61 @@ const (
|
||||
)
|
||||
|
||||
// Server returns an instance of http server with specified name.
|
||||
// Note that it panics if any error occurs duration instance creating.
|
||||
func Server(name ...interface{}) *ghttp.Server {
|
||||
instanceKey := fmt.Sprintf("%s.%v", frameCoreComponentNameServer, name)
|
||||
return instances.GetOrSetFuncLock(instanceKey, func() interface{} {
|
||||
s := ghttp.GetServer(name...)
|
||||
// To avoid file no found error while it's not necessary.
|
||||
if Config().Available() {
|
||||
var (
|
||||
serverConfigMap map[string]interface{}
|
||||
serverLoggerConfigMap map[string]interface{}
|
||||
)
|
||||
nodeKey, _ := gutil.MapPossibleItemByKey(Config().GetMap("."), configNodeNameServer)
|
||||
if nodeKey == "" {
|
||||
nodeKey = configNodeNameServer
|
||||
var (
|
||||
ctx = context.Background()
|
||||
instanceName = ghttp.DefaultServerName
|
||||
instanceKey = fmt.Sprintf("%s.%v", frameCoreComponentNameServer, name)
|
||||
)
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
instanceName = gconv.String(name[0])
|
||||
}
|
||||
return localInstances.GetOrSetFuncLock(instanceKey, func() interface{} {
|
||||
s := ghttp.GetServer(instanceName)
|
||||
// It ignores returned error to avoid file no found error while it's not necessary.
|
||||
var (
|
||||
serverConfigMap map[string]interface{}
|
||||
serverLoggerConfigMap map[string]interface{}
|
||||
configNodeName = configNodeNameServer
|
||||
)
|
||||
if configData, _ := Config().Data(ctx); len(configData) > 0 {
|
||||
if v, _ := gutil.MapPossibleItemByKey(configData, configNodeNameServer); v != "" {
|
||||
configNodeName = v
|
||||
}
|
||||
// Server configuration.
|
||||
serverConfigMap = Config().GetMap(fmt.Sprintf(`%s.%s`, nodeKey, s.GetName()))
|
||||
if len(serverConfigMap) == 0 {
|
||||
serverConfigMap = Config().GetMap(nodeKey)
|
||||
}
|
||||
if len(serverConfigMap) > 0 {
|
||||
if err := s.SetConfigWithMap(serverConfigMap); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
// Server logger configuration.
|
||||
serverLoggerConfigMap = Config().GetMap(
|
||||
fmt.Sprintf(`%s.%s.%s`, nodeKey, s.GetName(), configNodeNameLogger),
|
||||
)
|
||||
if len(serverLoggerConfigMap) > 0 {
|
||||
if err := s.Logger().SetConfigWithMap(serverLoggerConfigMap); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
// As it might use template feature,
|
||||
// it initialize the view instance as well.
|
||||
_ = getViewInstance()
|
||||
}
|
||||
// Server configuration.
|
||||
certainConfigNodeName := fmt.Sprintf(`%s.%s`, configNodeName, s.GetName())
|
||||
if v, _ := Config().Get(ctx, certainConfigNodeName); !v.IsEmpty() {
|
||||
serverConfigMap = v.Map()
|
||||
}
|
||||
if len(serverConfigMap) == 0 {
|
||||
if v, _ := Config().Get(ctx, configNodeName); !v.IsEmpty() {
|
||||
serverConfigMap = v.Map()
|
||||
}
|
||||
}
|
||||
if len(serverConfigMap) > 0 {
|
||||
if err := s.SetConfigWithMap(serverConfigMap); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
// The configuration is not necessary, so it just prints internal logs.
|
||||
intlog.Printf(ctx, `missing configuration for HTTP server "%s"`, instanceName)
|
||||
}
|
||||
|
||||
// Server logger configuration checks.
|
||||
serverLoggerNodeName := fmt.Sprintf(`%s.%s.%s`, configNodeName, s.GetName(), configNodeNameLogger)
|
||||
if v, _ := Config().Get(ctx, serverLoggerNodeName); !v.IsEmpty() {
|
||||
serverLoggerConfigMap = v.Map()
|
||||
}
|
||||
if len(serverLoggerConfigMap) > 0 {
|
||||
if err := s.Logger().SetConfigWithMap(serverLoggerConfigMap); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
// As it might use template feature,
|
||||
// it initializes the view instance as well.
|
||||
_ = getViewInstance()
|
||||
return s
|
||||
}).(*ghttp.Server)
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package gins
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/os/gview"
|
||||
"github.com/gogf/gf/util/gutil"
|
||||
@ -19,38 +20,48 @@ const (
|
||||
|
||||
// View returns an instance of View with default settings.
|
||||
// The parameter `name` is the name for the instance.
|
||||
// Note that it panics if any error occurs duration instance creating.
|
||||
func View(name ...string) *gview.View {
|
||||
instanceName := gview.DefaultName
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
instanceName = name[0]
|
||||
}
|
||||
instanceKey := fmt.Sprintf("%s.%s", frameCoreComponentNameViewer, instanceName)
|
||||
return instances.GetOrSetFuncLock(instanceKey, func() interface{} {
|
||||
return localInstances.GetOrSetFuncLock(instanceKey, func() interface{} {
|
||||
return getViewInstance(instanceName)
|
||||
}).(*gview.View)
|
||||
}
|
||||
|
||||
func getViewInstance(name ...string) *gview.View {
|
||||
instanceName := gview.DefaultName
|
||||
var (
|
||||
ctx = context.Background()
|
||||
instanceName = gview.DefaultName
|
||||
)
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
instanceName = name[0]
|
||||
}
|
||||
view := gview.Instance(instanceName)
|
||||
// To avoid file no found error while it's not necessary.
|
||||
if Config().Available() {
|
||||
var m map[string]interface{}
|
||||
nodeKey, _ := gutil.MapPossibleItemByKey(Config().GetMap("."), configNodeNameViewer)
|
||||
if nodeKey == "" {
|
||||
nodeKey = configNodeNameViewer
|
||||
var (
|
||||
configMap map[string]interface{}
|
||||
configNodeName = configNodeNameViewer
|
||||
)
|
||||
if configData, _ := Config().Data(ctx); len(configData) > 0 {
|
||||
if v, _ := gutil.MapPossibleItemByKey(configData, configNodeNameViewer); v != "" {
|
||||
configNodeName = v
|
||||
}
|
||||
m = Config().GetMap(fmt.Sprintf(`%s.%s`, nodeKey, instanceName))
|
||||
if len(m) == 0 {
|
||||
m = Config().GetMap(nodeKey)
|
||||
}
|
||||
if v, _ := Config().Get(ctx, fmt.Sprintf(`%s.%s`, configNodeName, instanceName)); !v.IsEmpty() {
|
||||
configMap = v.Map()
|
||||
}
|
||||
if len(configMap) == 0 {
|
||||
if v, _ := Config().Get(ctx, configNodeName); !v.IsEmpty() {
|
||||
configMap = v.Map()
|
||||
}
|
||||
if len(m) > 0 {
|
||||
if err := view.SetConfigWithMap(m); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
if len(configMap) > 0 {
|
||||
if err := view.SetConfigWithMap(configMap); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return view
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package gins_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/debug/gdebug"
|
||||
"github.com/gogf/gf/frame/gins"
|
||||
@ -21,6 +22,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.Background()
|
||||
configContent = gfile.GetContents(
|
||||
gdebug.TestDataPath("config", "config.toml"),
|
||||
)
|
||||
@ -48,14 +50,14 @@ func Test_Config2(t *testing.T) {
|
||||
err = gfile.PutContents(gfile.Join(dirPath, name), configContent)
|
||||
t.Assert(err, nil)
|
||||
|
||||
err = gins.Config().AddPath(dirPath)
|
||||
err = gins.Config().GetAdapter().(*gcfg.AdapterFile).AddPath(dirPath)
|
||||
t.Assert(err, nil)
|
||||
|
||||
defer gins.Config().Clear()
|
||||
defer gins.Config().GetAdapter().(*gcfg.AdapterFile).Clear()
|
||||
|
||||
t.Assert(gins.Config().Get("test"), "v=1")
|
||||
t.Assert(gins.Config().Get("database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().Get("redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config().MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
})
|
||||
// for gfsnotify callbacks to refresh cache of config file
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
@ -72,14 +74,14 @@ func Test_Config2(t *testing.T) {
|
||||
err = gfile.PutContents(gfile.Join(dirPath, name), configContent)
|
||||
t.Assert(err, nil)
|
||||
|
||||
err = gins.Config().AddPath(dirPath)
|
||||
err = gins.Config().GetAdapter().(*gcfg.AdapterFile).AddPath(dirPath)
|
||||
t.Assert(err, nil)
|
||||
|
||||
defer gins.Config().Clear()
|
||||
defer gins.Config().GetAdapter().(*gcfg.AdapterFile).Clear()
|
||||
|
||||
t.Assert(gins.Config().Get("test"), "v=1")
|
||||
t.Assert(gins.Config().Get("database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().Get("redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config().MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
|
||||
// for gfsnotify callbacks to refresh cache of config file
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
@ -98,15 +100,15 @@ func Test_Config3(t *testing.T) {
|
||||
err = gfile.PutContents(gfile.Join(dirPath, name), configContent)
|
||||
t.Assert(err, nil)
|
||||
|
||||
err = gins.Config("test").AddPath(dirPath)
|
||||
err = gins.Config("test").GetAdapter().(*gcfg.AdapterFile).AddPath(dirPath)
|
||||
t.Assert(err, nil)
|
||||
|
||||
defer gins.Config("test").Clear()
|
||||
gins.Config("test").SetFileName("test.toml")
|
||||
defer gins.Config("test").GetAdapter().(*gcfg.AdapterFile).Clear()
|
||||
gins.Config("test").GetAdapter().(*gcfg.AdapterFile).SetFileName("test.toml")
|
||||
|
||||
t.Assert(gins.Config("test").Get("test"), "v=1")
|
||||
t.Assert(gins.Config("test").Get("database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").Get("redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
})
|
||||
// for gfsnotify callbacks to refresh cache of config file
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
@ -122,15 +124,15 @@ func Test_Config3(t *testing.T) {
|
||||
err = gfile.PutContents(gfile.Join(dirPath, name), configContent)
|
||||
t.Assert(err, nil)
|
||||
|
||||
err = gins.Config("test").AddPath(dirPath)
|
||||
err = gins.Config("test").GetAdapter().(*gcfg.AdapterFile).AddPath(dirPath)
|
||||
t.Assert(err, nil)
|
||||
|
||||
defer gins.Config("test").Clear()
|
||||
gins.Config("test").SetFileName("test.toml")
|
||||
defer gins.Config("test").GetAdapter().(*gcfg.AdapterFile).Clear()
|
||||
gins.Config("test").GetAdapter().(*gcfg.AdapterFile).SetFileName("test.toml")
|
||||
|
||||
t.Assert(gins.Config("test").Get("test"), "v=1")
|
||||
t.Assert(gins.Config("test").Get("database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").Get("redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
})
|
||||
// for gfsnotify callbacks to refresh cache of config file for next unit testing case.
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
@ -144,12 +146,12 @@ func Test_Config4(t *testing.T) {
|
||||
err := gfile.PutContents(file, configContent)
|
||||
t.Assert(err, nil)
|
||||
defer gfile.Remove(file)
|
||||
defer gins.Config().Clear()
|
||||
defer gins.Config().GetAdapter().(*gcfg.AdapterFile).Clear()
|
||||
|
||||
t.Assert(gins.Config().AddPath(path), nil)
|
||||
t.Assert(gins.Config().Get("test"), "v=1")
|
||||
t.Assert(gins.Config().Get("database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().Get("redis.disk"), "127.0.0.1:6379,0")
|
||||
t.Assert(gins.Config().GetAdapter().(*gcfg.AdapterFile).AddPath(path), nil)
|
||||
t.Assert(gins.Config().MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
})
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
@ -159,11 +161,11 @@ func Test_Config4(t *testing.T) {
|
||||
err := gfile.PutContents(file, configContent)
|
||||
t.Assert(err, nil)
|
||||
defer gfile.Remove(file)
|
||||
defer gins.Config().Clear()
|
||||
t.Assert(gins.Config().AddPath(path), nil)
|
||||
t.Assert(gins.Config().Get("test"), "v=1")
|
||||
t.Assert(gins.Config().Get("database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().Get("redis.disk"), "127.0.0.1:6379,0")
|
||||
defer gins.Config().GetAdapter().(*gcfg.AdapterFile).Clear()
|
||||
t.Assert(gins.Config().GetAdapter().(*gcfg.AdapterFile).AddPath(path), nil)
|
||||
t.Assert(gins.Config().MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config().MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
})
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
@ -173,12 +175,12 @@ func Test_Config4(t *testing.T) {
|
||||
err := gfile.PutContents(file, configContent)
|
||||
t.Assert(err, nil)
|
||||
defer gfile.Remove(file)
|
||||
defer gins.Config("test").Clear()
|
||||
gins.Config("test").SetFileName("test.toml")
|
||||
t.Assert(gins.Config("test").AddPath(path), nil)
|
||||
t.Assert(gins.Config("test").Get("test"), "v=1")
|
||||
t.Assert(gins.Config("test").Get("database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").Get("redis.disk"), "127.0.0.1:6379,0")
|
||||
defer gins.Config("test").GetAdapter().(*gcfg.AdapterFile).Clear()
|
||||
gins.Config("test").GetAdapter().(*gcfg.AdapterFile).SetFileName("test.toml")
|
||||
t.Assert(gins.Config("test").GetAdapter().(*gcfg.AdapterFile).AddPath(path), nil)
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
})
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
@ -188,12 +190,12 @@ func Test_Config4(t *testing.T) {
|
||||
err := gfile.PutContents(file, configContent)
|
||||
t.Assert(err, nil)
|
||||
defer gfile.Remove(file)
|
||||
defer gins.Config().Clear()
|
||||
gins.Config("test").SetFileName("test.toml")
|
||||
t.Assert(gins.Config("test").AddPath(path), nil)
|
||||
t.Assert(gins.Config("test").Get("test"), "v=1")
|
||||
t.Assert(gins.Config("test").Get("database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").Get("redis.disk"), "127.0.0.1:6379,0")
|
||||
defer gins.Config().GetAdapter().(*gcfg.AdapterFile).Clear()
|
||||
gins.Config("test").GetAdapter().(*gcfg.AdapterFile).SetFileName("test.toml")
|
||||
t.Assert(gins.Config("test").GetAdapter().(*gcfg.AdapterFile).AddPath(path), nil)
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "test"), "v=1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "database.default.1.host"), "127.0.0.1")
|
||||
t.Assert(gins.Config("test").MustGet(ctx, "redis.disk"), "127.0.0.1:6379,0")
|
||||
})
|
||||
}
|
||||
func Test_Basic2(t *testing.T) {
|
||||
@ -206,6 +208,6 @@ func Test_Basic2(t *testing.T) {
|
||||
_ = gfile.Remove(path)
|
||||
}()
|
||||
|
||||
t.Assert(gins.Config().Get("log-path"), "logs")
|
||||
t.Assert(gins.Config().MustGet(ctx, "log-path"), "logs")
|
||||
})
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ package gins_test
|
||||
import (
|
||||
"github.com/gogf/gf/debug/gdebug"
|
||||
"github.com/gogf/gf/frame/gins"
|
||||
"github.com/gogf/gf/os/gcfg"
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
"testing"
|
||||
"time"
|
||||
@ -32,10 +33,10 @@ func Test_Database(t *testing.T) {
|
||||
err = gfile.PutContents(gfile.Join(dirPath, name), databaseContent)
|
||||
t.Assert(err, nil)
|
||||
|
||||
err = gins.Config().AddPath(dirPath)
|
||||
err = gins.Config().GetAdapter().(*gcfg.AdapterFile).AddPath(dirPath)
|
||||
t.Assert(err, nil)
|
||||
|
||||
defer gins.Config().Clear()
|
||||
defer gins.Config().GetAdapter().(*gcfg.AdapterFile).Clear()
|
||||
|
||||
// for gfsnotify callbacks to refresh cache of config file
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
@ -9,6 +9,7 @@ package gins_test
|
||||
import (
|
||||
"github.com/gogf/gf/debug/gdebug"
|
||||
"github.com/gogf/gf/frame/gins"
|
||||
"github.com/gogf/gf/os/gcfg"
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
"testing"
|
||||
"time"
|
||||
@ -33,10 +34,10 @@ func Test_Redis(t *testing.T) {
|
||||
err = gfile.PutContents(gfile.Join(dirPath, name), redisContent)
|
||||
t.Assert(err, nil)
|
||||
|
||||
err = gins.Config().AddPath(dirPath)
|
||||
err = gins.Config().GetAdapter().(*gcfg.AdapterFile).AddPath(dirPath)
|
||||
t.Assert(err, nil)
|
||||
|
||||
defer gins.Config().Clear()
|
||||
defer gins.Config().GetAdapter().(*gcfg.AdapterFile).Clear()
|
||||
|
||||
// for gfsnotify callbacks to refresh cache of config file
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
@ -54,9 +54,9 @@ func Test_View_Config(t *testing.T) {
|
||||
// view1 test1
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
dirPath := gdebug.TestDataPath("view1")
|
||||
gcfg.SetContent(gfile.GetContents(gfile.Join(dirPath, "config.toml")))
|
||||
defer gcfg.ClearContent()
|
||||
defer instances.Clear()
|
||||
Config().GetAdapter().(*gcfg.AdapterFile).SetContent(gfile.GetContents(gfile.Join(dirPath, "config.toml")))
|
||||
defer Config().GetAdapter().(*gcfg.AdapterFile).ClearContent()
|
||||
defer localInstances.Clear()
|
||||
|
||||
view := View("test1")
|
||||
t.AssertNE(view, nil)
|
||||
@ -76,9 +76,9 @@ func Test_View_Config(t *testing.T) {
|
||||
// view1 test2
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
dirPath := gdebug.TestDataPath("view1")
|
||||
gcfg.SetContent(gfile.GetContents(gfile.Join(dirPath, "config.toml")))
|
||||
defer gcfg.ClearContent()
|
||||
defer instances.Clear()
|
||||
Config().GetAdapter().(*gcfg.AdapterFile).SetContent(gfile.GetContents(gfile.Join(dirPath, "config.toml")))
|
||||
defer Config().GetAdapter().(*gcfg.AdapterFile).ClearContent()
|
||||
defer localInstances.Clear()
|
||||
|
||||
view := View("test2")
|
||||
t.AssertNE(view, nil)
|
||||
@ -98,9 +98,9 @@ func Test_View_Config(t *testing.T) {
|
||||
// view2
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
dirPath := gdebug.TestDataPath("view2")
|
||||
gcfg.SetContent(gfile.GetContents(gfile.Join(dirPath, "config.toml")))
|
||||
defer gcfg.ClearContent()
|
||||
defer instances.Clear()
|
||||
Config().GetAdapter().(*gcfg.AdapterFile).SetContent(gfile.GetContents(gfile.Join(dirPath, "config.toml")))
|
||||
defer Config().GetAdapter().(*gcfg.AdapterFile).ClearContent()
|
||||
defer localInstances.Clear()
|
||||
|
||||
view := View()
|
||||
t.AssertNE(view, nil)
|
||||
@ -120,9 +120,9 @@ func Test_View_Config(t *testing.T) {
|
||||
// view2
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
dirPath := gdebug.TestDataPath("view2")
|
||||
gcfg.SetContent(gfile.GetContents(gfile.Join(dirPath, "config.toml")))
|
||||
defer gcfg.ClearContent()
|
||||
defer instances.Clear()
|
||||
Config().GetAdapter().(*gcfg.AdapterFile).SetContent(gfile.GetContents(gfile.Join(dirPath, "config.toml")))
|
||||
defer Config().GetAdapter().(*gcfg.AdapterFile).ClearContent()
|
||||
defer localInstances.Clear()
|
||||
|
||||
view := View("test100")
|
||||
t.AssertNE(view, nil)
|
||||
|
||||
@ -107,9 +107,9 @@ const (
|
||||
HookAfterOutput = "HOOK_AFTER_OUTPUT"
|
||||
ServerStatusStopped = 0
|
||||
ServerStatusRunning = 1
|
||||
DefaultServerName = "default"
|
||||
DefaultDomainName = "default"
|
||||
supportedHttpMethods = "GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE"
|
||||
defaultServerName = "default"
|
||||
defaultDomainName = "default"
|
||||
defaultMethod = "ALL"
|
||||
handlerTypeHandler = 1
|
||||
handlerTypeObject = 2
|
||||
|
||||
@ -92,8 +92,8 @@ func (r *Response) buildInVars(params ...map[string]interface{}) map[string]inte
|
||||
})
|
||||
// Note that it should assign no Config variable to template
|
||||
// if there's no configuration file.
|
||||
if c := gcfg.Instance(); c.Available() {
|
||||
m["Config"] = c.Map()
|
||||
if v, _ := gcfg.Instance().Data(r.Request.Context()); len(v) > 0 {
|
||||
m["Config"] = v
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ func serverProcessInit() {
|
||||
// Note that the parameter <name> should be unique for different servers. It returns an existing
|
||||
// server instance if given <name> is already existing in the server mapping.
|
||||
func GetServer(name ...interface{}) *Server {
|
||||
serverName := defaultServerName
|
||||
serverName := DefaultServerName
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
serverName = gconv.String(name[0])
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ func StartPProfServer(port int, pattern ...string) {
|
||||
|
||||
// EnablePProf enables PProf feature for server.
|
||||
func (s *Server) EnablePProf(pattern ...string) {
|
||||
s.Domain(defaultDomainName).EnablePProf(pattern...)
|
||||
s.Domain(DefaultDomainName).EnablePProf(pattern...)
|
||||
}
|
||||
|
||||
// EnablePProf enables PProf feature for server of specified domain.
|
||||
|
||||
@ -39,7 +39,7 @@ func (s *Server) routerMapKey(hook, method, path, domain string) string {
|
||||
// parsePattern parses the given pattern to domain, method and path variable.
|
||||
func (s *Server) parsePattern(pattern string) (domain, method, path string, err error) {
|
||||
path = strings.TrimSpace(pattern)
|
||||
domain = defaultDomainName
|
||||
domain = DefaultDomainName
|
||||
method = defaultMethod
|
||||
if array, err := gregex.MatchString(`([a-zA-Z]+):(.+)`, pattern); len(array) > 1 && err == nil {
|
||||
path = strings.TrimSpace(array[2])
|
||||
|
||||
@ -106,7 +106,7 @@ func (s *Server) searchHandlers(method, path, domain string) (parsedItems []*han
|
||||
)
|
||||
|
||||
// Default domain has the most priority when iteration.
|
||||
for _, domain := range []string{defaultDomainName, domain} {
|
||||
for _, domain := range []string{DefaultDomainName, domain} {
|
||||
p, ok := s.serveTree[domain]
|
||||
if !ok {
|
||||
continue
|
||||
|
||||
@ -12,7 +12,7 @@ import (
|
||||
|
||||
// getStatusHandler retrieves and returns the handler for given status code.
|
||||
func (s *Server) getStatusHandler(status int, r *Request) []HandlerFunc {
|
||||
domains := []string{r.GetHost(), defaultDomainName}
|
||||
domains := []string{r.GetHost(), DefaultDomainName}
|
||||
for _, domain := range domains {
|
||||
if f, ok := s.statusHandlerMap[s.statusHandlerKey(status, domain)]; ok {
|
||||
return f
|
||||
@ -37,7 +37,7 @@ func (s *Server) statusHandlerKey(status int, domain string) string {
|
||||
|
||||
// BindStatusHandler registers handler for given status code.
|
||||
func (s *Server) BindStatusHandler(status int, handler HandlerFunc) {
|
||||
s.addStatusHandler(s.statusHandlerKey(status, defaultDomainName), handler)
|
||||
s.addStatusHandler(s.statusHandlerKey(status, DefaultDomainName), handler)
|
||||
}
|
||||
|
||||
// BindStatusHandlerByMap registers handler for given status code using map.
|
||||
|
||||
@ -54,7 +54,7 @@ const (
|
||||
)
|
||||
|
||||
// NewAdapterMemory creates and returns a new memory cache object.
|
||||
func NewAdapterMemory(lruCap ...int) Adapter {
|
||||
func NewAdapterMemory(lruCap ...int) *AdapterMemory {
|
||||
c := &AdapterMemory{
|
||||
data: newAdapterMemoryData(),
|
||||
lruGetList: glist.New(true),
|
||||
|
||||
@ -30,7 +30,7 @@ func New(lruCap ...int) *Cache {
|
||||
}
|
||||
// Here may be a "timer leak" if adapter is manually changed from memory adapter.
|
||||
// Do not worry about this, as adapter is less changed, and it does nothing if it's not used.
|
||||
gtimer.AddSingleton(time.Second, memAdapter.(*AdapterMemory).syncEventAndClearExpired)
|
||||
gtimer.AddSingleton(time.Second, memAdapter.syncEventAndClearExpired)
|
||||
return c
|
||||
}
|
||||
|
||||
|
||||
186
os/gcfg/gcfg.go
186
os/gcfg/gcfg.go
@ -9,97 +9,141 @@ package gcfg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/container/gmap"
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/os/gcmd"
|
||||
)
|
||||
|
||||
// Config is the configuration manager.
|
||||
type Config struct {
|
||||
defaultName string // Default configuration file name.
|
||||
searchPaths *garray.StrArray // Searching path array.
|
||||
jsonMap *gmap.StrAnyMap // The pared JSON objects for configuration files.
|
||||
violenceCheck bool // Whether do violence check in value index searching. It affects the performance when set true(false in default).
|
||||
adapter Adapter
|
||||
dataMap *gmap.StrAnyMap
|
||||
}
|
||||
|
||||
const (
|
||||
DefaultName = "config" // DefaultName is the default group name for instance usage.
|
||||
DefaultConfigFile = "config.toml" // DefaultConfigFile is the default configuration file name.
|
||||
commandEnvKeyForFile = "gf.gcfg.file" // commandEnvKeyForFile is the configuration key for command argument or environment configuring file name.
|
||||
commandEnvKeyForPath = "gf.gcfg.path" // commandEnvKeyForPath is the configuration key for command argument or environment configuring directory path.
|
||||
commandEnvKeyForErrorPrint = "gf.gcfg.errorprint" // commandEnvKeyForErrorPrint is used to specify the key controlling error printing to stdout.
|
||||
DefaultName = "config" // DefaultName is the default group name for instance usage.
|
||||
)
|
||||
|
||||
var (
|
||||
supportedFileTypes = []string{"toml", "yaml", "yml", "json", "ini", "xml"} // All supported file types suffixes.
|
||||
resourceTryFiles = []string{"", "/", "config/", "config", "/config", "/config/"} // Prefix array for trying searching in resource manager.
|
||||
instances = gmap.NewStrAnyMap(true) // Instances map containing configuration instances.
|
||||
customConfigContentMap = gmap.NewStrStrMap(true) // Customized configuration content.
|
||||
)
|
||||
|
||||
// SetContent sets customized configuration content for specified `file`.
|
||||
// The `file` is unnecessary param, default is DefaultConfigFile.
|
||||
func SetContent(content string, file ...string) {
|
||||
name := DefaultConfigFile
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
// New creates and returns a Config object with default adapter of AdapterFile.
|
||||
func New() (*Config, error) {
|
||||
adapterFile, err := NewAdapterFile()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Clear file cache for instances which cached `name`.
|
||||
instances.LockFunc(func(m map[string]interface{}) {
|
||||
if customConfigContentMap.Contains(name) {
|
||||
for _, v := range m {
|
||||
v.(*Config).jsonMap.Remove(name)
|
||||
return &Config{
|
||||
adapter: adapterFile,
|
||||
dataMap: gmap.NewStrAnyMap(true),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewWithAdapter creates and returns a Config object with given adapter.
|
||||
func NewWithAdapter(adapter Adapter) *Config {
|
||||
return &Config{
|
||||
adapter: adapter,
|
||||
dataMap: gmap.NewStrAnyMap(true),
|
||||
}
|
||||
}
|
||||
|
||||
// Instance returns an instance of Config with default settings.
|
||||
// The parameter `name` is the name for the instance. But very note that, if the file "name.toml"
|
||||
// exists in the configuration directory, it then sets it as the default configuration file. The
|
||||
// toml file type is the default configuration file type.
|
||||
func Instance(name ...string) *Config {
|
||||
key := DefaultName
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
key = name[0]
|
||||
}
|
||||
return localInstances.GetOrSetFuncLock(key, func() interface{} {
|
||||
adapter, err := NewAdapterFile()
|
||||
if err != nil {
|
||||
intlog.Error(context.Background(), err)
|
||||
return nil
|
||||
}
|
||||
// If it's not using default configuration or its configuration file is not available,
|
||||
// it searches the possible configuration file according to the name and all supported
|
||||
// file types.
|
||||
if key != DefaultName || !adapter.Available() {
|
||||
for _, fileType := range supportedFileTypes {
|
||||
if file := fmt.Sprintf(`%s.%s`, key, fileType); adapter.Available(file) {
|
||||
adapter.SetFileName(file)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
customConfigContentMap.Set(name, content)
|
||||
})
|
||||
return NewWithAdapter(adapter)
|
||||
}).(*Config)
|
||||
}
|
||||
|
||||
// GetContent returns customized configuration content for specified `file`.
|
||||
// The `file` is unnecessary param, default is DefaultConfigFile.
|
||||
func GetContent(file ...string) string {
|
||||
name := DefaultConfigFile
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
}
|
||||
return customConfigContentMap.Get(name)
|
||||
// SetAdapter sets the adapter of current Config object.
|
||||
func (c *Config) SetAdapter(adapter Adapter) {
|
||||
c.adapter = adapter
|
||||
}
|
||||
|
||||
// RemoveContent removes the global configuration with specified `file`.
|
||||
// If `name` is not passed, it removes configuration of the default group name.
|
||||
func RemoveContent(file ...string) {
|
||||
name := DefaultConfigFile
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
}
|
||||
// Clear file cache for instances which cached `name`.
|
||||
instances.LockFunc(func(m map[string]interface{}) {
|
||||
if customConfigContentMap.Contains(name) {
|
||||
for _, v := range m {
|
||||
v.(*Config).jsonMap.Remove(name)
|
||||
}
|
||||
customConfigContentMap.Remove(name)
|
||||
// GetAdapter returns the adapter of current Config object.
|
||||
func (c *Config) GetAdapter() Adapter {
|
||||
return c.adapter
|
||||
}
|
||||
|
||||
// Set sets value with specified `pattern`.
|
||||
// It supports hierarchical data access by char separator, which is '.' in default.
|
||||
// It is commonly used for updates certain configuration value in runtime.
|
||||
func (c *Config) Set(ctx context.Context, pattern string, value interface{}) {
|
||||
c.dataMap.Set(pattern, value)
|
||||
}
|
||||
|
||||
// Get retrieves and returns value by specified `pattern`.
|
||||
// It returns all values of current Json object if `pattern` is given empty or string ".".
|
||||
// It returns nil if no value found by `pattern`.
|
||||
//
|
||||
// It returns a default value specified by `def` if value for `pattern` is not found.
|
||||
func (c *Config) Get(ctx context.Context, pattern string, def ...interface{}) (*gvar.Var, error) {
|
||||
var (
|
||||
err error
|
||||
value interface{}
|
||||
)
|
||||
if value = c.dataMap.Get(pattern); value == nil {
|
||||
value, err = c.adapter.Get(ctx, pattern)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
})
|
||||
|
||||
intlog.Printf(context.TODO(), `RemoveContent: %s`, name)
|
||||
}
|
||||
|
||||
// ClearContent removes all global configuration contents.
|
||||
func ClearContent() {
|
||||
customConfigContentMap.Clear()
|
||||
// Clear cache for all instances.
|
||||
instances.LockFunc(func(m map[string]interface{}) {
|
||||
for _, v := range m {
|
||||
v.(*Config).jsonMap.Clear()
|
||||
if value == nil && len(def) > 0 {
|
||||
return gvar.New(def[0]), nil
|
||||
}
|
||||
}
|
||||
return gvar.New(value), nil
|
||||
}
|
||||
|
||||
// Data retrieves and returns all configuration data as map type.
|
||||
func (c *Config) Data(ctx context.Context) (data map[string]interface{}, err error) {
|
||||
adapterData, err := c.adapter.Data(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = make(map[string]interface{})
|
||||
for k, v := range adapterData {
|
||||
data[k] = v
|
||||
}
|
||||
c.dataMap.Iterator(func(k string, v interface{}) bool {
|
||||
data[k] = v
|
||||
return true
|
||||
})
|
||||
|
||||
intlog.Print(context.TODO(), `RemoveConfig`)
|
||||
return
|
||||
}
|
||||
|
||||
// errorPrint checks whether printing error to stdout.
|
||||
func errorPrint() bool {
|
||||
return gcmd.GetOptWithEnv(commandEnvKeyForErrorPrint, true).Bool()
|
||||
// MustGet acts as function Get, but it panics if error occurs.
|
||||
func (c *Config) MustGet(ctx context.Context, pattern string, def ...interface{}) *gvar.Var {
|
||||
v, err := c.Get(ctx, pattern, def...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return gvar.New(v)
|
||||
}
|
||||
|
||||
// MustData acts as function Data, but it panics if error occurs.
|
||||
func (c *Config) MustData(ctx context.Context) map[string]interface{} {
|
||||
v, err := c.Data(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
20
os/gcfg/gcfg_adaper.go
Normal file
20
os/gcfg/gcfg_adaper.go
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcfg
|
||||
|
||||
import "context"
|
||||
|
||||
// Adapter is the interface for configuration retrieving.
|
||||
type Adapter interface {
|
||||
// Get retrieves and returns value by specified `pattern`.
|
||||
Get(ctx context.Context, pattern string) (value interface{}, err error)
|
||||
|
||||
// Data retrieves and returns all configuration data as map type.
|
||||
// Note that this function may lead lots of memory usage if configuration data is too large,
|
||||
// you can implement this function if necessary.
|
||||
Data(ctx context.Context) (data map[string]interface{}, err error)
|
||||
}
|
||||
275
os/gcfg/gcfg_adapter_file.go
Normal file
275
os/gcfg/gcfg_adapter_file.go
Normal file
@ -0,0 +1,275 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcfg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/container/gmap"
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gogf/gf/encoding/gjson"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/os/gcmd"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/os/gfsnotify"
|
||||
"github.com/gogf/gf/os/gres"
|
||||
"github.com/gogf/gf/util/gmode"
|
||||
)
|
||||
|
||||
type AdapterFile struct {
|
||||
defaultName string // Default configuration file name.
|
||||
searchPaths *garray.StrArray // Searching path array.
|
||||
jsonMap *gmap.StrAnyMap // The pared JSON objects for configuration files.
|
||||
violenceCheck bool // Whether it does violence check in value index searching. It affects the performance when set true(false in default).
|
||||
}
|
||||
|
||||
const (
|
||||
DefaultConfigFile = "config.toml" // DefaultConfigFile is the default configuration file name.
|
||||
commandEnvKeyForFile = "gf.gcfg.file" // commandEnvKeyForFile is the configuration key for command argument or environment configuring file name.
|
||||
commandEnvKeyForPath = "gf.gcfg.path" // commandEnvKeyForPath is the configuration key for command argument or environment configuring directory path.
|
||||
)
|
||||
|
||||
var (
|
||||
supportedFileTypes = []string{"toml", "yaml", "yml", "json", "ini", "xml"} // All supported file types suffixes.
|
||||
resourceTryFiles = []string{"", "/", "config/", "config", "/config", "/config/"} // Prefix array for trying searching in resource manager.
|
||||
localInstances = gmap.NewStrAnyMap(true) // Instances map containing configuration instances.
|
||||
customConfigContentMap = gmap.NewStrStrMap(true) // Customized configuration content.
|
||||
)
|
||||
|
||||
// NewAdapterFile returns a new configuration management object.
|
||||
// The parameter `file` specifies the default configuration file name for reading.
|
||||
func NewAdapterFile(file ...string) (*AdapterFile, error) {
|
||||
var (
|
||||
err error
|
||||
name = DefaultConfigFile
|
||||
)
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
} else {
|
||||
// Custom default configuration file name from command line or environment.
|
||||
if customFile := gcmd.GetOptWithEnv(commandEnvKeyForFile).String(); customFile != "" {
|
||||
name = customFile
|
||||
}
|
||||
}
|
||||
c := &AdapterFile{
|
||||
defaultName: name,
|
||||
searchPaths: garray.NewStrArray(true),
|
||||
jsonMap: gmap.NewStrAnyMap(true),
|
||||
}
|
||||
// Customized dir path from env/cmd.
|
||||
if customPath := gcmd.GetOptWithEnv(commandEnvKeyForPath).String(); customPath != "" {
|
||||
if gfile.Exists(customPath) {
|
||||
if err = c.SetPath(customPath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return nil, gerror.Newf(`configuration directory path "%s" does not exist`, customPath)
|
||||
}
|
||||
} else {
|
||||
// ================================================================================
|
||||
// Automatic searching directories.
|
||||
// It does not affect adapter object cresting if these directories do not exist.
|
||||
// ================================================================================
|
||||
|
||||
// Dir path of working dir.
|
||||
if err := c.AddPath(gfile.Pwd()); err != nil {
|
||||
intlog.Error(context.TODO(), err)
|
||||
}
|
||||
|
||||
// Dir path of main package.
|
||||
if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) {
|
||||
if err := c.AddPath(mainPath); err != nil {
|
||||
intlog.Error(context.TODO(), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Dir path of binary.
|
||||
if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) {
|
||||
if err := c.AddPath(selfPath); err != nil {
|
||||
intlog.Error(context.TODO(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// SetViolenceCheck sets whether to perform hierarchical conflict checking.
|
||||
// This feature needs to be enabled when there is a level symbol in the key name.
|
||||
// It is off in default.
|
||||
//
|
||||
// Note that, turning on this feature is quite expensive, and it is not recommended
|
||||
// allowing separators in the key names. It is best to avoid this on the application side.
|
||||
func (c *AdapterFile) SetViolenceCheck(check bool) {
|
||||
c.violenceCheck = check
|
||||
c.Clear()
|
||||
}
|
||||
|
||||
// SetFileName sets the default configuration file name.
|
||||
func (c *AdapterFile) SetFileName(name string) {
|
||||
c.defaultName = name
|
||||
}
|
||||
|
||||
// GetFileName returns the default configuration file name.
|
||||
func (c *AdapterFile) GetFileName() string {
|
||||
return c.defaultName
|
||||
}
|
||||
|
||||
// Get retrieves and returns value by specified `pattern`.
|
||||
// It returns all values of current Json object if `pattern` is given empty or string ".".
|
||||
// It returns nil if no value found by `pattern`.
|
||||
//
|
||||
// We can also access slice item by its index number in `pattern` like:
|
||||
// "list.10", "array.0.name", "array.0.1.id".
|
||||
//
|
||||
// It returns a default value specified by `def` if value for `pattern` is not found.
|
||||
func (c *AdapterFile) Get(ctx context.Context, pattern string) (value interface{}, err error) {
|
||||
j, err := c.getJson()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if j != nil {
|
||||
return j.Get(pattern), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Data retrieves and returns all configuration data as map type.
|
||||
func (c *AdapterFile) Data(ctx context.Context) (data map[string]interface{}, err error) {
|
||||
j, err := c.getJson()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if j != nil {
|
||||
return j.GetVar(".").Map(), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// MustGet acts as function Get, but it panics if error occurs.
|
||||
func (c *AdapterFile) MustGet(ctx context.Context, pattern string) *gvar.Var {
|
||||
v, err := c.Get(ctx, pattern)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return gvar.New(v)
|
||||
}
|
||||
|
||||
// Clear removes all parsed configuration files content cache,
|
||||
// which will force reload configuration content from file.
|
||||
func (c *AdapterFile) Clear() {
|
||||
c.jsonMap.Clear()
|
||||
}
|
||||
|
||||
// Dump prints current Json object with more manually readable.
|
||||
func (c *AdapterFile) Dump() {
|
||||
if j, _ := c.getJson(); j != nil {
|
||||
j.Dump()
|
||||
}
|
||||
}
|
||||
|
||||
// Available checks and returns whether configuration of given `file` is available.
|
||||
func (c *AdapterFile) Available(fileName ...string) bool {
|
||||
var (
|
||||
usedFileName string
|
||||
)
|
||||
if len(fileName) > 0 && fileName[0] != "" {
|
||||
usedFileName = fileName[0]
|
||||
} else {
|
||||
usedFileName = c.defaultName
|
||||
}
|
||||
if path, _ := c.GetFilePath(usedFileName); path != "" {
|
||||
return true
|
||||
}
|
||||
if c.GetContent(usedFileName) != "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// autoCheckAndAddMainPkgPathToSearchPaths automatically checks and adds directory path of package main
|
||||
// to the searching path list if it's currently in development environment.
|
||||
func (c *AdapterFile) autoCheckAndAddMainPkgPathToSearchPaths() {
|
||||
if gmode.IsDevelop() {
|
||||
mainPkgPath := gfile.MainPkgPath()
|
||||
if mainPkgPath != "" {
|
||||
if !c.searchPaths.Contains(mainPkgPath) {
|
||||
c.searchPaths.Append(mainPkgPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// getJson returns a *gjson.Json object for the specified `file` content.
|
||||
// It would print error if file reading fails. It returns nil if any error occurs.
|
||||
func (c *AdapterFile) getJson(fileName ...string) (configJson *gjson.Json, err error) {
|
||||
var (
|
||||
usedFileName = c.defaultName
|
||||
)
|
||||
if len(fileName) > 0 && fileName[0] != "" {
|
||||
usedFileName = fileName[0]
|
||||
} else {
|
||||
usedFileName = c.defaultName
|
||||
}
|
||||
result := c.jsonMap.GetOrSetFuncLock(usedFileName, func() interface{} {
|
||||
var (
|
||||
content string
|
||||
filePath string
|
||||
)
|
||||
// The configured content can be any kind of data type different from its file type.
|
||||
isFromConfigContent := true
|
||||
if content = c.GetContent(usedFileName); content == "" {
|
||||
isFromConfigContent = false
|
||||
filePath, err = c.GetFilePath(usedFileName)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if filePath == "" {
|
||||
return nil
|
||||
}
|
||||
if file := gres.Get(filePath); file != nil {
|
||||
content = string(file.Content())
|
||||
} else {
|
||||
content = gfile.GetContents(filePath)
|
||||
}
|
||||
}
|
||||
// Note that the underlying configuration json object operations are concurrent safe.
|
||||
dataType := gfile.ExtName(usedFileName)
|
||||
if gjson.IsValidDataType(dataType) && !isFromConfigContent {
|
||||
configJson, err = gjson.LoadContentType(dataType, content, true)
|
||||
} else {
|
||||
configJson, err = gjson.LoadContent(content, true)
|
||||
}
|
||||
if err == nil {
|
||||
configJson.SetViolenceCheck(c.violenceCheck)
|
||||
// Add monitor for this configuration file,
|
||||
// any changes of this file will refresh its cache in Config object.
|
||||
if filePath != "" && !gres.Contains(filePath) {
|
||||
_, err = gfsnotify.Add(filePath, func(event *gfsnotify.Event) {
|
||||
c.jsonMap.Remove(usedFileName)
|
||||
})
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return configJson
|
||||
}
|
||||
if err != nil {
|
||||
if filePath != "" {
|
||||
err = gerror.WrapCodef(gcode.CodeOperationFailed, err, `load config file "%s" failed`, filePath)
|
||||
} else {
|
||||
err = gerror.WrapCode(gcode.CodeOperationFailed, err, `load configuration failed`)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if result != nil {
|
||||
return result.(*gjson.Json), err
|
||||
}
|
||||
return
|
||||
}
|
||||
84
os/gcfg/gcfg_adapter_file_content.go
Normal file
84
os/gcfg/gcfg_adapter_file_content.go
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcfg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
)
|
||||
|
||||
// SetContent sets customized configuration content for specified `file`.
|
||||
// The `file` is unnecessary param, default is DefaultConfigFile.
|
||||
func (c *AdapterFile) SetContent(content string, file ...string) {
|
||||
name := DefaultConfigFile
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
}
|
||||
// Clear file cache for instances which cached `name`.
|
||||
localInstances.LockFunc(func(m map[string]interface{}) {
|
||||
if customConfigContentMap.Contains(name) {
|
||||
for _, v := range m {
|
||||
if configInstance, ok := v.(*Config); ok {
|
||||
if fileConfig, ok := configInstance.GetAdapter().(*AdapterFile); ok {
|
||||
fileConfig.jsonMap.Remove(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
customConfigContentMap.Set(name, content)
|
||||
})
|
||||
}
|
||||
|
||||
// GetContent returns customized configuration content for specified `file`.
|
||||
// The `file` is unnecessary param, default is DefaultConfigFile.
|
||||
func (c *AdapterFile) GetContent(file ...string) string {
|
||||
name := DefaultConfigFile
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
}
|
||||
return customConfigContentMap.Get(name)
|
||||
}
|
||||
|
||||
// RemoveContent removes the global configuration with specified `file`.
|
||||
// If `name` is not passed, it removes configuration of the default group name.
|
||||
func (c *AdapterFile) RemoveContent(file ...string) {
|
||||
name := DefaultConfigFile
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
}
|
||||
// Clear file cache for instances which cached `name`.
|
||||
localInstances.LockFunc(func(m map[string]interface{}) {
|
||||
if customConfigContentMap.Contains(name) {
|
||||
for _, v := range m {
|
||||
if configInstance, ok := v.(*Config); ok {
|
||||
if fileConfig, ok := configInstance.GetAdapter().(*AdapterFile); ok {
|
||||
fileConfig.jsonMap.Remove(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
customConfigContentMap.Remove(name)
|
||||
}
|
||||
})
|
||||
|
||||
intlog.Printf(context.TODO(), `RemoveContent: %s`, name)
|
||||
}
|
||||
|
||||
// ClearContent removes all global configuration contents.
|
||||
func (c *AdapterFile) ClearContent() {
|
||||
customConfigContentMap.Clear()
|
||||
// Clear cache for all instances.
|
||||
localInstances.LockFunc(func(m map[string]interface{}) {
|
||||
for _, v := range m {
|
||||
if configInstance, ok := v.(*Config); ok {
|
||||
if fileConfig, ok := configInstance.GetAdapter().(*AdapterFile); ok {
|
||||
fileConfig.jsonMap.Clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
intlog.Print(context.TODO(), `RemoveConfig`)
|
||||
}
|
||||
208
os/gcfg/gcfg_adapter_file_path.go
Normal file
208
os/gcfg/gcfg_adapter_file_path.go
Normal file
@ -0,0 +1,208 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcfg
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/os/gres"
|
||||
"github.com/gogf/gf/os/gspath"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
)
|
||||
|
||||
// SetPath sets the configuration directory path for file search.
|
||||
// The parameter `path` can be absolute or relative path,
|
||||
// but absolute path is strongly recommended.
|
||||
func (c *AdapterFile) SetPath(path string) (err error) {
|
||||
var (
|
||||
isDir = false
|
||||
realPath = ""
|
||||
)
|
||||
if file := gres.Get(path); file != nil {
|
||||
realPath = path
|
||||
isDir = file.FileInfo().IsDir()
|
||||
} else {
|
||||
// Absolute path.
|
||||
realPath = gfile.RealPath(path)
|
||||
if realPath == "" {
|
||||
// Relative path.
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for _, v := range array {
|
||||
if path, _ := gspath.Search(v, path); path != "" {
|
||||
realPath = path
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
if realPath != "" {
|
||||
isDir = gfile.IsDir(realPath)
|
||||
}
|
||||
}
|
||||
// Path not exist.
|
||||
if realPath == "" {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
if c.searchPaths.Len() > 0 {
|
||||
buffer.WriteString(fmt.Sprintf(`SetPath failed: cannot find directory "%s" in following paths:`, path))
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for k, v := range array {
|
||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", k+1, v))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
buffer.WriteString(fmt.Sprintf(`SetPath failed: path "%s" does not exist`, path))
|
||||
}
|
||||
return gerror.NewCode(gcode.CodeOperationFailed, buffer.String())
|
||||
}
|
||||
// Should be a directory.
|
||||
if !isDir {
|
||||
return gerror.NewCodef(
|
||||
gcode.CodeInvalidParameter,
|
||||
`SetPath failed: path "%s" should be directory type`,
|
||||
path,
|
||||
)
|
||||
}
|
||||
// Repeated path check.
|
||||
if c.searchPaths.Search(realPath) != -1 {
|
||||
return nil
|
||||
}
|
||||
c.jsonMap.Clear()
|
||||
c.searchPaths.Clear()
|
||||
c.searchPaths.Append(realPath)
|
||||
intlog.Print(context.TODO(), "SetPath:", realPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddPath adds an absolute or relative path to the search paths.
|
||||
func (c *AdapterFile) AddPath(path string) (err error) {
|
||||
var (
|
||||
isDir = false
|
||||
realPath = ""
|
||||
)
|
||||
// It firstly checks the resource manager,
|
||||
// and then checks the filesystem for the path.
|
||||
if file := gres.Get(path); file != nil {
|
||||
realPath = path
|
||||
isDir = file.FileInfo().IsDir()
|
||||
} else {
|
||||
// Absolute path.
|
||||
realPath = gfile.RealPath(path)
|
||||
if realPath == "" {
|
||||
// Relative path.
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for _, v := range array {
|
||||
if path, _ := gspath.Search(v, path); path != "" {
|
||||
realPath = path
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
if realPath != "" {
|
||||
isDir = gfile.IsDir(realPath)
|
||||
}
|
||||
}
|
||||
if realPath == "" {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
if c.searchPaths.Len() > 0 {
|
||||
buffer.WriteString(fmt.Sprintf(`AddPath failed: cannot find directory "%s" in following paths:`, path))
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for k, v := range array {
|
||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", k+1, v))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
buffer.WriteString(fmt.Sprintf(`AddPath failed: path "%s" does not exist`, path))
|
||||
}
|
||||
return gerror.NewCode(gcode.CodeOperationFailed, buffer.String())
|
||||
}
|
||||
if !isDir {
|
||||
return gerror.NewCodef(gcode.CodeInvalidParameter, `AddPath failed: path "%s" should be directory type`, path)
|
||||
}
|
||||
// Repeated path check.
|
||||
if c.searchPaths.Search(realPath) != -1 {
|
||||
return nil
|
||||
}
|
||||
c.searchPaths.Append(realPath)
|
||||
intlog.Print(context.TODO(), "AddPath:", realPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFilePath returns the absolute configuration file path for the given filename by `file`.
|
||||
// If `file` is not passed, it returns the configuration file path of the default name.
|
||||
// It returns an empty `path` string and an error if the given `file` does not exist.
|
||||
func (c *AdapterFile) GetFilePath(fileName ...string) (path string, err error) {
|
||||
var (
|
||||
usedFileName = c.defaultName
|
||||
)
|
||||
if len(fileName) > 0 {
|
||||
usedFileName = fileName[0]
|
||||
}
|
||||
// Searching resource manager.
|
||||
if !gres.IsEmpty() {
|
||||
for _, v := range resourceTryFiles {
|
||||
if file := gres.Get(v + usedFileName); file != nil {
|
||||
path = file.Name()
|
||||
return
|
||||
}
|
||||
}
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for _, prefix := range array {
|
||||
for _, v := range resourceTryFiles {
|
||||
if file := gres.Get(prefix + v + usedFileName); file != nil {
|
||||
path = file.Name()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
c.autoCheckAndAddMainPkgPathToSearchPaths()
|
||||
// Searching the file system.
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for _, prefix := range array {
|
||||
prefix = gstr.TrimRight(prefix, `\/`)
|
||||
if path, _ = gspath.Search(prefix, usedFileName); path != "" {
|
||||
return
|
||||
}
|
||||
if path, _ = gspath.Search(prefix+gfile.Separator+"config", usedFileName); path != "" {
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
// If it cannot find the path of `file`, it formats and returns a detailed error.
|
||||
if path == "" {
|
||||
var (
|
||||
buffer = bytes.NewBuffer(nil)
|
||||
)
|
||||
if c.searchPaths.Len() > 0 {
|
||||
buffer.WriteString(fmt.Sprintf(
|
||||
`config file "%s" not found in resource manager or the following system searching paths:`,
|
||||
usedFileName,
|
||||
))
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
index := 1
|
||||
for _, v := range array {
|
||||
v = gstr.TrimRight(v, `\/`)
|
||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", index, v))
|
||||
index++
|
||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", index, v+gfile.Separator+"config"))
|
||||
index++
|
||||
}
|
||||
})
|
||||
} else {
|
||||
buffer.WriteString(fmt.Sprintf(`cannot find config file "%s" with no path configured`, usedFileName))
|
||||
}
|
||||
err = gerror.NewCode(gcode.CodeOperationFailed, buffer.String())
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -1,424 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcfg
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/container/garray"
|
||||
"github.com/gogf/gf/container/gmap"
|
||||
"github.com/gogf/gf/encoding/gjson"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/os/gcmd"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/os/gfsnotify"
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/os/gres"
|
||||
"github.com/gogf/gf/os/gspath"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
"github.com/gogf/gf/util/gmode"
|
||||
)
|
||||
|
||||
// New returns a new configuration management object.
|
||||
// The parameter `file` specifies the default configuration file name for reading.
|
||||
func New(file ...string) *Config {
|
||||
name := DefaultConfigFile
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
} else {
|
||||
// Custom default configuration file name from command line or environment.
|
||||
if customFile := gcmd.GetOptWithEnv(commandEnvKeyForFile).String(); customFile != "" {
|
||||
name = customFile
|
||||
}
|
||||
}
|
||||
c := &Config{
|
||||
defaultName: name,
|
||||
searchPaths: garray.NewStrArray(true),
|
||||
jsonMap: gmap.NewStrAnyMap(true),
|
||||
}
|
||||
// Customized dir path from env/cmd.
|
||||
if customPath := gcmd.GetOptWithEnv(commandEnvKeyForPath).String(); customPath != "" {
|
||||
if gfile.Exists(customPath) {
|
||||
_ = c.SetPath(customPath)
|
||||
} else {
|
||||
if errorPrint() {
|
||||
glog.Errorf("[gcfg] Configuration directory path does not exist: %s", customPath)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Dir path of working dir.
|
||||
if err := c.AddPath(gfile.Pwd()); err != nil {
|
||||
intlog.Error(context.TODO(), err)
|
||||
}
|
||||
|
||||
// Dir path of main package.
|
||||
if mainPath := gfile.MainPkgPath(); mainPath != "" && gfile.Exists(mainPath) {
|
||||
if err := c.AddPath(mainPath); err != nil {
|
||||
intlog.Error(context.TODO(), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Dir path of binary.
|
||||
if selfPath := gfile.SelfDir(); selfPath != "" && gfile.Exists(selfPath) {
|
||||
if err := c.AddPath(selfPath); err != nil {
|
||||
intlog.Error(context.TODO(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Instance returns an instance of Config with default settings.
|
||||
// The parameter `name` is the name for the instance. But very note that, if the file "name.toml"
|
||||
// exists in the configuration directory, it then sets it as the default configuration file. The
|
||||
// toml file type is the default configuration file type.
|
||||
func Instance(name ...string) *Config {
|
||||
key := DefaultName
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
key = name[0]
|
||||
}
|
||||
return instances.GetOrSetFuncLock(key, func() interface{} {
|
||||
c := New()
|
||||
// If it's not using default configuration or its configuration file is not available,
|
||||
// it searches the possible configuration file according to the name and all supported
|
||||
// file types.
|
||||
if key != DefaultName || !c.Available() {
|
||||
for _, fileType := range supportedFileTypes {
|
||||
if file := fmt.Sprintf(`%s.%s`, key, fileType); c.Available(file) {
|
||||
c.SetFileName(file)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return c
|
||||
}).(*Config)
|
||||
}
|
||||
|
||||
// SetPath sets the configuration directory path for file search.
|
||||
// The parameter `path` can be absolute or relative path,
|
||||
// but absolute path is strongly recommended.
|
||||
func (c *Config) SetPath(path string) error {
|
||||
var (
|
||||
isDir = false
|
||||
realPath = ""
|
||||
)
|
||||
if file := gres.Get(path); file != nil {
|
||||
realPath = path
|
||||
isDir = file.FileInfo().IsDir()
|
||||
} else {
|
||||
// Absolute path.
|
||||
realPath = gfile.RealPath(path)
|
||||
if realPath == "" {
|
||||
// Relative path.
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for _, v := range array {
|
||||
if path, _ := gspath.Search(v, path); path != "" {
|
||||
realPath = path
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
if realPath != "" {
|
||||
isDir = gfile.IsDir(realPath)
|
||||
}
|
||||
}
|
||||
// Path not exist.
|
||||
if realPath == "" {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
if c.searchPaths.Len() > 0 {
|
||||
buffer.WriteString(fmt.Sprintf("[gcfg] SetPath failed: cannot find directory \"%s\" in following paths:", path))
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for k, v := range array {
|
||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", k+1, v))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
buffer.WriteString(fmt.Sprintf(`[gcfg] SetPath failed: path "%s" does not exist`, path))
|
||||
}
|
||||
err := gerror.NewCode(gcode.CodeOperationFailed, buffer.String())
|
||||
if errorPrint() {
|
||||
glog.Error(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
// Should be a directory.
|
||||
if !isDir {
|
||||
err := gerror.NewCodef(
|
||||
gcode.CodeInvalidParameter,
|
||||
`[gcfg] SetPath failed: path "%s" should be directory type`,
|
||||
path,
|
||||
)
|
||||
if errorPrint() {
|
||||
glog.Error(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
// Repeated path check.
|
||||
if c.searchPaths.Search(realPath) != -1 {
|
||||
return nil
|
||||
}
|
||||
c.jsonMap.Clear()
|
||||
c.searchPaths.Clear()
|
||||
c.searchPaths.Append(realPath)
|
||||
intlog.Print(context.TODO(), "SetPath:", realPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetViolenceCheck sets whether to perform hierarchical conflict checking.
|
||||
// This feature needs to be enabled when there is a level symbol in the key name.
|
||||
// It is off in default.
|
||||
//
|
||||
// Note that, turning on this feature is quite expensive, and it is not recommended
|
||||
// allowing separators in the key names. It is best to avoid this on the application side.
|
||||
func (c *Config) SetViolenceCheck(check bool) {
|
||||
c.violenceCheck = check
|
||||
c.Clear()
|
||||
}
|
||||
|
||||
// AddPath adds an absolute or relative path to the search paths.
|
||||
func (c *Config) AddPath(path string) error {
|
||||
var (
|
||||
isDir = false
|
||||
realPath = ""
|
||||
)
|
||||
// It firstly checks the resource manager,
|
||||
// and then checks the filesystem for the path.
|
||||
if file := gres.Get(path); file != nil {
|
||||
realPath = path
|
||||
isDir = file.FileInfo().IsDir()
|
||||
} else {
|
||||
// Absolute path.
|
||||
realPath = gfile.RealPath(path)
|
||||
if realPath == "" {
|
||||
// Relative path.
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for _, v := range array {
|
||||
if path, _ := gspath.Search(v, path); path != "" {
|
||||
realPath = path
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
if realPath != "" {
|
||||
isDir = gfile.IsDir(realPath)
|
||||
}
|
||||
}
|
||||
if realPath == "" {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
if c.searchPaths.Len() > 0 {
|
||||
buffer.WriteString(fmt.Sprintf("[gcfg] AddPath failed: cannot find directory \"%s\" in following paths:", path))
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for k, v := range array {
|
||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", k+1, v))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
buffer.WriteString(fmt.Sprintf(`[gcfg] AddPath failed: path "%s" does not exist`, path))
|
||||
}
|
||||
err := gerror.NewCode(gcode.CodeOperationFailed, buffer.String())
|
||||
if errorPrint() {
|
||||
glog.Error(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
if !isDir {
|
||||
err := gerror.NewCodef(gcode.CodeInvalidParameter, `[gcfg] AddPath failed: path "%s" should be directory type`, path)
|
||||
if errorPrint() {
|
||||
glog.Error(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
// Repeated path check.
|
||||
if c.searchPaths.Search(realPath) != -1 {
|
||||
return nil
|
||||
}
|
||||
c.searchPaths.Append(realPath)
|
||||
intlog.Print(context.TODO(), "AddPath:", realPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFileName sets the default configuration file name.
|
||||
func (c *Config) SetFileName(name string) *Config {
|
||||
c.defaultName = name
|
||||
return c
|
||||
}
|
||||
|
||||
// GetFileName returns the default configuration file name.
|
||||
func (c *Config) GetFileName() string {
|
||||
return c.defaultName
|
||||
}
|
||||
|
||||
// Available checks and returns whether configuration of given `file` is available.
|
||||
func (c *Config) Available(file ...string) bool {
|
||||
var name string
|
||||
if len(file) > 0 && file[0] != "" {
|
||||
name = file[0]
|
||||
} else {
|
||||
name = c.defaultName
|
||||
}
|
||||
if path, _ := c.GetFilePath(name); path != "" {
|
||||
return true
|
||||
}
|
||||
if GetContent(name) != "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetFilePath returns the absolute configuration file path for the given filename by `file`.
|
||||
// If `file` is not passed, it returns the configuration file path of the default name.
|
||||
// It returns an empty `path` string and an error if the given `file` does not exist.
|
||||
func (c *Config) GetFilePath(file ...string) (path string, err error) {
|
||||
name := c.defaultName
|
||||
if len(file) > 0 {
|
||||
name = file[0]
|
||||
}
|
||||
// Searching resource manager.
|
||||
if !gres.IsEmpty() {
|
||||
for _, v := range resourceTryFiles {
|
||||
if file := gres.Get(v + name); file != nil {
|
||||
path = file.Name()
|
||||
return
|
||||
}
|
||||
}
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for _, prefix := range array {
|
||||
for _, v := range resourceTryFiles {
|
||||
if file := gres.Get(prefix + v + name); file != nil {
|
||||
path = file.Name()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
c.autoCheckAndAddMainPkgPathToSearchPaths()
|
||||
// Searching the file system.
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
for _, prefix := range array {
|
||||
prefix = gstr.TrimRight(prefix, `\/`)
|
||||
if path, _ = gspath.Search(prefix, name); path != "" {
|
||||
return
|
||||
}
|
||||
if path, _ = gspath.Search(prefix+gfile.Separator+"config", name); path != "" {
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
// If it cannot find the path of `file`, it formats and returns a detailed error.
|
||||
if path == "" {
|
||||
var (
|
||||
buffer = bytes.NewBuffer(nil)
|
||||
)
|
||||
if c.searchPaths.Len() > 0 {
|
||||
buffer.WriteString(fmt.Sprintf(`[gcfg] cannot find config file "%s" in resource manager or the following paths:`, name))
|
||||
c.searchPaths.RLockFunc(func(array []string) {
|
||||
index := 1
|
||||
for _, v := range array {
|
||||
v = gstr.TrimRight(v, `\/`)
|
||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", index, v))
|
||||
index++
|
||||
buffer.WriteString(fmt.Sprintf("\n%d. %s", index, v+gfile.Separator+"config"))
|
||||
index++
|
||||
}
|
||||
})
|
||||
} else {
|
||||
buffer.WriteString(fmt.Sprintf("[gcfg] cannot find config file \"%s\" with no path configured", name))
|
||||
}
|
||||
err = gerror.NewCode(gcode.CodeOperationFailed, buffer.String())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// autoCheckAndAddMainPkgPathToSearchPaths automatically checks and adds directory path of package main
|
||||
// to the searching path list if it's currently in development environment.
|
||||
func (c *Config) autoCheckAndAddMainPkgPathToSearchPaths() {
|
||||
if gmode.IsDevelop() {
|
||||
mainPkgPath := gfile.MainPkgPath()
|
||||
if mainPkgPath != "" {
|
||||
if !c.searchPaths.Contains(mainPkgPath) {
|
||||
c.searchPaths.Append(mainPkgPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// getJson returns a *gjson.Json object for the specified `file` content.
|
||||
// It would print error if file reading fails. It return nil if any error occurs.
|
||||
func (c *Config) getJson(file ...string) *gjson.Json {
|
||||
var name string
|
||||
if len(file) > 0 && file[0] != "" {
|
||||
name = file[0]
|
||||
} else {
|
||||
name = c.defaultName
|
||||
}
|
||||
r := c.jsonMap.GetOrSetFuncLock(name, func() interface{} {
|
||||
var (
|
||||
err error
|
||||
content string
|
||||
filePath string
|
||||
)
|
||||
// The configured content can be any kind of data type different from its file type.
|
||||
isFromConfigContent := true
|
||||
if content = GetContent(name); content == "" {
|
||||
isFromConfigContent = false
|
||||
filePath, err = c.GetFilePath(name)
|
||||
if err != nil && errorPrint() {
|
||||
glog.Error(err)
|
||||
}
|
||||
if filePath == "" {
|
||||
return nil
|
||||
}
|
||||
if file := gres.Get(filePath); file != nil {
|
||||
content = string(file.Content())
|
||||
} else {
|
||||
content = gfile.GetContents(filePath)
|
||||
}
|
||||
}
|
||||
// Note that the underlying configuration json object operations are concurrent safe.
|
||||
var (
|
||||
j *gjson.Json
|
||||
)
|
||||
dataType := gfile.ExtName(name)
|
||||
if gjson.IsValidDataType(dataType) && !isFromConfigContent {
|
||||
j, err = gjson.LoadContentType(dataType, content, true)
|
||||
} else {
|
||||
j, err = gjson.LoadContent(content, true)
|
||||
}
|
||||
if err == nil {
|
||||
j.SetViolenceCheck(c.violenceCheck)
|
||||
// Add monitor for this configuration file,
|
||||
// any changes of this file will refresh its cache in Config object.
|
||||
if filePath != "" && !gres.Contains(filePath) {
|
||||
_, err = gfsnotify.Add(filePath, func(event *gfsnotify.Event) {
|
||||
c.jsonMap.Remove(name)
|
||||
})
|
||||
if err != nil && errorPrint() {
|
||||
glog.Error(err)
|
||||
}
|
||||
}
|
||||
return j
|
||||
}
|
||||
if errorPrint() {
|
||||
if filePath != "" {
|
||||
glog.Criticalf(`[gcfg] load config file "%s" failed: %s`, filePath, err.Error())
|
||||
} else {
|
||||
glog.Criticalf(`[gcfg] load configuration failed: %s`, err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if r != nil {
|
||||
return r.(*gjson.Json)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -1,403 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcfg
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/encoding/gjson"
|
||||
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
)
|
||||
|
||||
// Set sets value with specified `pattern`.
|
||||
// It supports hierarchical data access by char separator, which is '.' in default.
|
||||
// It is commonly used for updates certain configuration value in runtime.
|
||||
func (c *Config) Set(pattern string, value interface{}) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.Set(pattern, value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get retrieves and returns value by specified `pattern`.
|
||||
// It returns all values of current Json object if `pattern` is given empty or string ".".
|
||||
// It returns nil if no value found by `pattern`.
|
||||
//
|
||||
// We can also access slice item by its index number in `pattern` like:
|
||||
// "list.10", "array.0.name", "array.0.1.id".
|
||||
//
|
||||
// It returns a default value specified by `def` if value for `pattern` is not found.
|
||||
func (c *Config) Get(pattern string, def ...interface{}) interface{} {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.Get(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetVar returns a gvar.Var with value by given `pattern`.
|
||||
func (c *Config) GetVar(pattern string, def ...interface{}) *gvar.Var {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetVar(pattern, def...)
|
||||
}
|
||||
return gvar.New(nil)
|
||||
}
|
||||
|
||||
// Contains checks whether the value by specified `pattern` exist.
|
||||
func (c *Config) Contains(pattern string) bool {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.Contains(pattern)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetMap retrieves and returns the value by specified `pattern` as map[string]interface{}.
|
||||
func (c *Config) GetMap(pattern string, def ...interface{}) map[string]interface{} {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetMap(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMapStrStr retrieves and returns the value by specified `pattern` as map[string]string.
|
||||
func (c *Config) GetMapStrStr(pattern string, def ...interface{}) map[string]string {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetMapStrStr(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetArray retrieves the value by specified `pattern`,
|
||||
// and converts it to a slice of []interface{}.
|
||||
func (c *Config) GetArray(pattern string, def ...interface{}) []interface{} {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetArray(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBytes retrieves the value by specified `pattern` and converts it to []byte.
|
||||
func (c *Config) GetBytes(pattern string, def ...interface{}) []byte {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetBytes(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetString retrieves the value by specified `pattern` and converts it to string.
|
||||
func (c *Config) GetString(pattern string, def ...interface{}) string {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetString(pattern, def...)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetStrings retrieves the value by specified `pattern` and converts it to []string.
|
||||
func (c *Config) GetStrings(pattern string, def ...interface{}) []string {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetStrings(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInterfaces is alias of GetArray.
|
||||
// See GetArray.
|
||||
func (c *Config) GetInterfaces(pattern string, def ...interface{}) []interface{} {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetInterfaces(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBool retrieves the value by specified `pattern`,
|
||||
// converts and returns it as bool.
|
||||
// It returns false when value is: "", 0, false, off, nil;
|
||||
// or returns true instead.
|
||||
func (c *Config) GetBool(pattern string, def ...interface{}) bool {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetBool(pattern, def...)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetFloat32 retrieves the value by specified `pattern` and converts it to float32.
|
||||
func (c *Config) GetFloat32(pattern string, def ...interface{}) float32 {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetFloat32(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetFloat64 retrieves the value by specified `pattern` and converts it to float64.
|
||||
func (c *Config) GetFloat64(pattern string, def ...interface{}) float64 {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetFloat64(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetFloats retrieves the value by specified `pattern` and converts it to []float64.
|
||||
func (c *Config) GetFloats(pattern string, def ...interface{}) []float64 {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetFloats(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInt retrieves the value by specified `pattern` and converts it to int.
|
||||
func (c *Config) GetInt(pattern string, def ...interface{}) int {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetInt(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetInt8 retrieves the value by specified `pattern` and converts it to int8.
|
||||
func (c *Config) GetInt8(pattern string, def ...interface{}) int8 {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetInt8(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetInt16 retrieves the value by specified `pattern` and converts it to int16.
|
||||
func (c *Config) GetInt16(pattern string, def ...interface{}) int16 {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetInt16(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetInt32 retrieves the value by specified `pattern` and converts it to int32.
|
||||
func (c *Config) GetInt32(pattern string, def ...interface{}) int32 {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetInt32(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetInt64 retrieves the value by specified `pattern` and converts it to int64.
|
||||
func (c *Config) GetInt64(pattern string, def ...interface{}) int64 {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetInt64(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetInts retrieves the value by specified `pattern` and converts it to []int.
|
||||
func (c *Config) GetInts(pattern string, def ...interface{}) []int {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetInts(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUint retrieves the value by specified `pattern` and converts it to uint.
|
||||
func (c *Config) GetUint(pattern string, def ...interface{}) uint {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetUint(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetUint8 retrieves the value by specified `pattern` and converts it to uint8.
|
||||
func (c *Config) GetUint8(pattern string, def ...interface{}) uint8 {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetUint8(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetUint16 retrieves the value by specified `pattern` and converts it to uint16.
|
||||
func (c *Config) GetUint16(pattern string, def ...interface{}) uint16 {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetUint16(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetUint32 retrieves the value by specified `pattern` and converts it to uint32.
|
||||
func (c *Config) GetUint32(pattern string, def ...interface{}) uint32 {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetUint32(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetUint64 retrieves the value by specified `pattern` and converts it to uint64.
|
||||
func (c *Config) GetUint64(pattern string, def ...interface{}) uint64 {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetUint64(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetTime retrieves the value by specified `pattern` and converts it to time.Time.
|
||||
func (c *Config) GetTime(pattern string, format ...string) time.Time {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetTime(pattern, format...)
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// GetDuration retrieves the value by specified `pattern` and converts it to time.Duration.
|
||||
func (c *Config) GetDuration(pattern string, def ...interface{}) time.Duration {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetDuration(pattern, def...)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetGTime retrieves the value by specified `pattern` and converts it to *gtime.Time.
|
||||
func (c *Config) GetGTime(pattern string, format ...string) *gtime.Time {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetGTime(pattern, format...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetJson gets the value by specified `pattern`,
|
||||
// and converts it to a un-concurrent-safe Json object.
|
||||
func (c *Config) GetJson(pattern string, def ...interface{}) *gjson.Json {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetJson(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetJsons gets the value by specified `pattern`,
|
||||
// and converts it to a slice of un-concurrent-safe Json object.
|
||||
func (c *Config) GetJsons(pattern string, def ...interface{}) []*gjson.Json {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetJsons(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetJsonMap gets the value by specified `pattern`,
|
||||
// and converts it to a map of un-concurrent-safe Json object.
|
||||
func (c *Config) GetJsonMap(pattern string, def ...interface{}) map[string]*gjson.Json {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetJsonMap(pattern, def...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetStruct retrieves the value by specified `pattern` and converts it to specified object
|
||||
// `pointer`. The `pointer` should be the pointer to an object.
|
||||
func (c *Config) GetStruct(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetStruct(pattern, pointer, mapping...)
|
||||
}
|
||||
return gerror.NewCode(gcode.CodeMissingConfiguration, "configuration not found")
|
||||
}
|
||||
|
||||
// GetStructs converts any slice to given struct slice.
|
||||
func (c *Config) GetStructs(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetStructs(pattern, pointer, mapping...)
|
||||
}
|
||||
return gerror.NewCode(gcode.CodeMissingConfiguration, "configuration not found")
|
||||
}
|
||||
|
||||
// GetMapToMap retrieves the value by specified `pattern` and converts it to specified map variable.
|
||||
// See gconv.MapToMap.
|
||||
func (c *Config) GetMapToMap(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetMapToMap(pattern, pointer, mapping...)
|
||||
}
|
||||
return gerror.NewCode(gcode.CodeMissingConfiguration, "configuration not found")
|
||||
}
|
||||
|
||||
// GetMapToMaps retrieves the value by specified `pattern` and converts it to specified map slice
|
||||
// variable.
|
||||
// See gconv.MapToMaps.
|
||||
func (c *Config) GetMapToMaps(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetMapToMaps(pattern, pointer, mapping...)
|
||||
}
|
||||
return gerror.NewCode(gcode.CodeMissingConfiguration, "configuration not found")
|
||||
}
|
||||
|
||||
// GetMapToMapsDeep retrieves the value by specified `pattern` and converts it to specified map slice
|
||||
// variable recursively.
|
||||
// See gconv.MapToMapsDeep.
|
||||
func (c *Config) GetMapToMapsDeep(pattern string, pointer interface{}, mapping ...map[string]string) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.GetMapToMapsDeep(pattern, pointer, mapping...)
|
||||
}
|
||||
return gerror.NewCode(gcode.CodeMissingConfiguration, "configuration not found")
|
||||
}
|
||||
|
||||
// Map converts current Json object to map[string]interface{}. It returns nil if fails.
|
||||
func (c *Config) Map() map[string]interface{} {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.Map()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Array converts current Json object to []interface{}.
|
||||
// It returns nil if fails.
|
||||
func (c *Config) Array() []interface{} {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.Array()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Struct converts current Json object to specified object.
|
||||
// The `pointer` should be a pointer type of *struct.
|
||||
func (c *Config) Struct(pointer interface{}, mapping ...map[string]string) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.Struct(pointer, mapping...)
|
||||
}
|
||||
return gerror.NewCode(gcode.CodeMissingConfiguration, "configuration not found")
|
||||
}
|
||||
|
||||
// Structs converts current Json object to specified object slice.
|
||||
// The `pointer` should be a pointer type of []struct/*struct.
|
||||
func (c *Config) Structs(pointer interface{}, mapping ...map[string]string) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.Structs(pointer, mapping...)
|
||||
}
|
||||
return gerror.NewCode(gcode.CodeMissingConfiguration, "configuration not found")
|
||||
}
|
||||
|
||||
// MapToMap converts current Json object to specified map variable.
|
||||
// The parameter of `pointer` should be type of *map.
|
||||
func (c *Config) MapToMap(pointer interface{}, mapping ...map[string]string) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.MapToMap(pointer, mapping...)
|
||||
}
|
||||
return gerror.NewCode(gcode.CodeMissingConfiguration, "configuration not found")
|
||||
}
|
||||
|
||||
// MapToMaps converts current Json object to specified map variable slice.
|
||||
// The parameter of `pointer` should be type of []map/*map.
|
||||
func (c *Config) MapToMaps(pointer interface{}, mapping ...map[string]string) error {
|
||||
if j := c.getJson(); j != nil {
|
||||
return j.MapToMaps(pointer, mapping...)
|
||||
}
|
||||
return gerror.NewCode(gcode.CodeMissingConfiguration, "configuration not found")
|
||||
}
|
||||
|
||||
// Clear removes all parsed configuration files content cache,
|
||||
// which will force reload configuration content from file.
|
||||
func (c *Config) Clear() {
|
||||
c.jsonMap.Clear()
|
||||
}
|
||||
|
||||
// Dump prints current Json object with more manually readable.
|
||||
func (c *Config) Dump() {
|
||||
if j := c.getJson(); j != nil {
|
||||
j.Dump()
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcfg_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/os/gcfg"
|
||||
)
|
||||
|
||||
func Example_mapSliceChange() {
|
||||
intlog.SetEnabled(false)
|
||||
defer intlog.SetEnabled(true)
|
||||
// For testing/example only.
|
||||
content := `{"map":{"key":"value"}, "slice":[59,90]}`
|
||||
gcfg.SetContent(content)
|
||||
defer gcfg.RemoveContent()
|
||||
|
||||
m := g.Cfg().GetMap("map")
|
||||
fmt.Println(m)
|
||||
|
||||
// Change the key-value pair.
|
||||
m["key"] = "john"
|
||||
|
||||
// It changes the underlying key-value pair.
|
||||
fmt.Println(g.Cfg().GetMap("map"))
|
||||
|
||||
s := g.Cfg().GetArray("slice")
|
||||
fmt.Println(s)
|
||||
|
||||
// Change the value of specified index.
|
||||
s[0] = 100
|
||||
|
||||
// It changes the underlying slice.
|
||||
fmt.Println(g.Cfg().GetArray("slice"))
|
||||
|
||||
// output:
|
||||
// map[key:value]
|
||||
// map[key:john]
|
||||
// [59 90]
|
||||
// [100 90]
|
||||
}
|
||||
15
os/gcfg/gcfg_z_init_test.go
Normal file
15
os/gcfg/gcfg_z_init_test.go
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gcfg_test
|
||||
|
||||
import "context"
|
||||
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
100
os/gcfg/gcfg_z_unit_adapter_file_test.go
Normal file
100
os/gcfg/gcfg_z_unit_adapter_file_test.go
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gcfg_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/os/gcfg"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAdapterFile_SetPath(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c, err := gcfg.NewAdapterFile("config.yml")
|
||||
t.AssertNil(err)
|
||||
|
||||
err = c.SetPath("/tmp")
|
||||
t.AssertNil(err)
|
||||
|
||||
err = c.SetPath("gcfg.go")
|
||||
t.AssertNE(err, nil)
|
||||
|
||||
v, err := c.Get(ctx, "name")
|
||||
t.AssertNE(err, nil)
|
||||
t.Assert(v, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAdapterFile_AddPath(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c, err := gcfg.NewAdapterFile("config.yml")
|
||||
t.AssertNil(err)
|
||||
|
||||
err = c.AddPath("/tmp")
|
||||
t.AssertNil(err)
|
||||
|
||||
err = c.AddPath("gcfg.go")
|
||||
t.AssertNE(err, nil)
|
||||
|
||||
v, err := c.Get(ctx, "name")
|
||||
t.AssertNE(err, nil)
|
||||
t.Assert(v, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAdapterFile_SetViolenceCheck(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c, err := gcfg.NewAdapterFile("config.yml")
|
||||
t.AssertNil(err)
|
||||
c.SetViolenceCheck(true)
|
||||
v, err := c.Get(ctx, "name")
|
||||
t.AssertNE(err, nil)
|
||||
t.Assert(v, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAdapterFile_FilePath(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c, err := gcfg.NewAdapterFile("config.yml")
|
||||
t.AssertNil(err)
|
||||
|
||||
path, _ := c.GetFilePath("tmp")
|
||||
t.Assert(path, "")
|
||||
|
||||
path, _ = c.GetFilePath("tmp")
|
||||
t.Assert(path, "")
|
||||
})
|
||||
}
|
||||
|
||||
func TestAdapterFile_Content(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c, err := gcfg.NewAdapterFile()
|
||||
t.AssertNil(err)
|
||||
|
||||
c.SetContent("gf", "config.yml")
|
||||
t.Assert(c.GetContent("config.yml"), "gf")
|
||||
c.SetContent("gf1", "config.yml")
|
||||
t.Assert(c.GetContent("config.yml"), "gf1")
|
||||
c.RemoveContent("config.yml")
|
||||
c.ClearContent()
|
||||
t.Assert(c.GetContent("name"), "")
|
||||
})
|
||||
}
|
||||
|
||||
func TestAdapterFile_With_UTF8_BOM(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c, err := gcfg.NewAdapterFile("test-cfg-with-utf8-bom")
|
||||
t.AssertNil(err)
|
||||
|
||||
t.Assert(c.SetPath("testdata"), nil)
|
||||
c.SetFileName("cfg-with-utf8-bom.toml")
|
||||
t.Assert(c.MustGet(ctx, "test.testInt"), 1)
|
||||
t.Assert(c.MustGet(ctx, "test.testStr"), "test")
|
||||
})
|
||||
}
|
||||
@ -9,22 +9,15 @@
|
||||
package gcfg_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
|
||||
"github.com/gogf/gf/encoding/gjson"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/os/gcfg"
|
||||
"github.com/gogf/gf/os/gfile"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func init() {
|
||||
os.Setenv("GF_GCFG_ERRORPRINT", "false")
|
||||
}
|
||||
|
||||
func Test_Basic1(t *testing.T) {
|
||||
config := `
|
||||
v1 = 1
|
||||
@ -42,46 +35,10 @@ array = [1,2,3]
|
||||
t.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
|
||||
c := gcfg.New()
|
||||
t.Assert(c.Get("v1"), 1)
|
||||
t.AssertEQ(c.GetInt("v1"), 1)
|
||||
t.AssertEQ(c.GetInt8("v1"), int8(1))
|
||||
t.AssertEQ(c.GetInt16("v1"), int16(1))
|
||||
t.AssertEQ(c.GetInt32("v1"), int32(1))
|
||||
t.AssertEQ(c.GetInt64("v1"), int64(1))
|
||||
t.AssertEQ(c.GetUint("v1"), uint(1))
|
||||
t.AssertEQ(c.GetUint8("v1"), uint8(1))
|
||||
t.AssertEQ(c.GetUint16("v1"), uint16(1))
|
||||
t.AssertEQ(c.GetUint32("v1"), uint32(1))
|
||||
t.AssertEQ(c.GetUint64("v1"), uint64(1))
|
||||
|
||||
t.AssertEQ(c.GetVar("v1").String(), "1")
|
||||
t.AssertEQ(c.GetVar("v1").Bool(), true)
|
||||
t.AssertEQ(c.GetVar("v2").String(), "true")
|
||||
t.AssertEQ(c.GetVar("v2").Bool(), true)
|
||||
|
||||
t.AssertEQ(c.GetString("v1"), "1")
|
||||
t.AssertEQ(c.GetFloat32("v4"), float32(1.23))
|
||||
t.AssertEQ(c.GetFloat64("v4"), float64(1.23))
|
||||
t.AssertEQ(c.GetString("v2"), "true")
|
||||
t.AssertEQ(c.GetBool("v2"), true)
|
||||
t.AssertEQ(c.GetBool("v3"), false)
|
||||
|
||||
t.AssertEQ(c.Contains("v1"), true)
|
||||
t.AssertEQ(c.Contains("v2"), true)
|
||||
t.AssertEQ(c.Contains("v3"), true)
|
||||
t.AssertEQ(c.Contains("v4"), true)
|
||||
t.AssertEQ(c.Contains("v5"), false)
|
||||
|
||||
t.AssertEQ(c.GetInts("array"), []int{1, 2, 3})
|
||||
t.AssertEQ(c.GetStrings("array"), []string{"1", "2", "3"})
|
||||
t.AssertEQ(c.GetArray("array"), []interface{}{1, 2, 3})
|
||||
t.AssertEQ(c.GetInterfaces("array"), []interface{}{1, 2, 3})
|
||||
t.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
"disk": "127.0.0.1:6379,0",
|
||||
"cache": "127.0.0.1:6379,1",
|
||||
})
|
||||
filepath, _ := c.GetFilePath()
|
||||
c, err := gcfg.New()
|
||||
t.AssertNil(err)
|
||||
t.Assert(c.MustGet(ctx, "v1"), 1)
|
||||
filepath, _ := c.GetAdapter().(*gcfg.AdapterFile).GetFilePath()
|
||||
t.AssertEQ(filepath, gfile.Pwd()+gfile.Separator+path)
|
||||
})
|
||||
}
|
||||
@ -96,8 +53,9 @@ func Test_Basic2(t *testing.T) {
|
||||
_ = gfile.Remove(path)
|
||||
}()
|
||||
|
||||
c := gcfg.New()
|
||||
t.Assert(c.Get("log-path"), "logs")
|
||||
c, err := gcfg.New()
|
||||
t.AssertNil(err)
|
||||
t.Assert(c.MustGet(ctx, "log-path"), "logs")
|
||||
})
|
||||
}
|
||||
|
||||
@ -112,49 +70,12 @@ array = [1,2,3]
|
||||
disk = "127.0.0.1:6379,0"
|
||||
cache = "127.0.0.1:6379,1"
|
||||
`
|
||||
gcfg.SetContent(content)
|
||||
defer gcfg.ClearContent()
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c := gcfg.New()
|
||||
t.Assert(c.Get("v1"), 1)
|
||||
t.AssertEQ(c.GetInt("v1"), 1)
|
||||
t.AssertEQ(c.GetInt8("v1"), int8(1))
|
||||
t.AssertEQ(c.GetInt16("v1"), int16(1))
|
||||
t.AssertEQ(c.GetInt32("v1"), int32(1))
|
||||
t.AssertEQ(c.GetInt64("v1"), int64(1))
|
||||
t.AssertEQ(c.GetUint("v1"), uint(1))
|
||||
t.AssertEQ(c.GetUint8("v1"), uint8(1))
|
||||
t.AssertEQ(c.GetUint16("v1"), uint16(1))
|
||||
t.AssertEQ(c.GetUint32("v1"), uint32(1))
|
||||
t.AssertEQ(c.GetUint64("v1"), uint64(1))
|
||||
|
||||
t.AssertEQ(c.GetVar("v1").String(), "1")
|
||||
t.AssertEQ(c.GetVar("v1").Bool(), true)
|
||||
t.AssertEQ(c.GetVar("v2").String(), "true")
|
||||
t.AssertEQ(c.GetVar("v2").Bool(), true)
|
||||
|
||||
t.AssertEQ(c.GetString("v1"), "1")
|
||||
t.AssertEQ(c.GetFloat32("v4"), float32(1.23))
|
||||
t.AssertEQ(c.GetFloat64("v4"), float64(1.23))
|
||||
t.AssertEQ(c.GetString("v2"), "true")
|
||||
t.AssertEQ(c.GetBool("v2"), true)
|
||||
t.AssertEQ(c.GetBool("v3"), false)
|
||||
|
||||
t.AssertEQ(c.Contains("v1"), true)
|
||||
t.AssertEQ(c.Contains("v2"), true)
|
||||
t.AssertEQ(c.Contains("v3"), true)
|
||||
t.AssertEQ(c.Contains("v4"), true)
|
||||
t.AssertEQ(c.Contains("v5"), false)
|
||||
|
||||
t.AssertEQ(c.GetInts("array"), []int{1, 2, 3})
|
||||
t.AssertEQ(c.GetStrings("array"), []string{"1", "2", "3"})
|
||||
t.AssertEQ(c.GetArray("array"), []interface{}{1, 2, 3})
|
||||
t.AssertEQ(c.GetInterfaces("array"), []interface{}{1, 2, 3})
|
||||
t.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
"disk": "127.0.0.1:6379,0",
|
||||
"cache": "127.0.0.1:6379,1",
|
||||
})
|
||||
c, err := gcfg.New()
|
||||
t.AssertNil(err)
|
||||
c.GetAdapter().(*gcfg.AdapterFile).SetContent(content)
|
||||
defer c.GetAdapter().(*gcfg.AdapterFile).ClearContent()
|
||||
t.Assert(c.MustGet(ctx, "v1"), 1)
|
||||
})
|
||||
}
|
||||
|
||||
@ -184,43 +105,38 @@ func Test_SetFileName(t *testing.T) {
|
||||
_ = gfile.Remove(path)
|
||||
}()
|
||||
|
||||
c := gcfg.New()
|
||||
config, err := gcfg.New()
|
||||
t.AssertNil(err)
|
||||
c := config.GetAdapter().(*gcfg.AdapterFile)
|
||||
c.SetFileName(path)
|
||||
t.Assert(c.Get("v1"), 1)
|
||||
t.AssertEQ(c.GetInt("v1"), 1)
|
||||
t.AssertEQ(c.GetInt8("v1"), int8(1))
|
||||
t.AssertEQ(c.GetInt16("v1"), int16(1))
|
||||
t.AssertEQ(c.GetInt32("v1"), int32(1))
|
||||
t.AssertEQ(c.GetInt64("v1"), int64(1))
|
||||
t.AssertEQ(c.GetUint("v1"), uint(1))
|
||||
t.AssertEQ(c.GetUint8("v1"), uint8(1))
|
||||
t.AssertEQ(c.GetUint16("v1"), uint16(1))
|
||||
t.AssertEQ(c.GetUint32("v1"), uint32(1))
|
||||
t.AssertEQ(c.GetUint64("v1"), uint64(1))
|
||||
t.Assert(c.MustGet(ctx, "v1"), 1)
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").Int(), 1)
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").Int8(), int8(1))
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").Int16(), int16(1))
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").Int32(), int32(1))
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").Int64(), int64(1))
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").Uint(), uint(1))
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").Uint8(), uint8(1))
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").Uint16(), uint16(1))
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").Uint32(), uint32(1))
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").Uint64(), uint64(1))
|
||||
|
||||
t.AssertEQ(c.GetVar("v1").String(), "1")
|
||||
t.AssertEQ(c.GetVar("v1").Bool(), true)
|
||||
t.AssertEQ(c.GetVar("v2").String(), "true")
|
||||
t.AssertEQ(c.GetVar("v2").Bool(), true)
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").String(), "1")
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").Bool(), true)
|
||||
t.AssertEQ(c.MustGet(ctx, "v2").String(), "true")
|
||||
t.AssertEQ(c.MustGet(ctx, "v2").Bool(), true)
|
||||
|
||||
t.AssertEQ(c.GetString("v1"), "1")
|
||||
t.AssertEQ(c.GetFloat32("v4"), float32(1.234))
|
||||
t.AssertEQ(c.GetFloat64("v4"), float64(1.234))
|
||||
t.AssertEQ(c.GetString("v2"), "true")
|
||||
t.AssertEQ(c.GetBool("v2"), true)
|
||||
t.AssertEQ(c.GetBool("v3"), false)
|
||||
t.AssertEQ(c.MustGet(ctx, "v1").String(), "1")
|
||||
t.AssertEQ(c.MustGet(ctx, "v4").Float32(), float32(1.234))
|
||||
t.AssertEQ(c.MustGet(ctx, "v4").Float64(), float64(1.234))
|
||||
t.AssertEQ(c.MustGet(ctx, "v2").String(), "true")
|
||||
t.AssertEQ(c.MustGet(ctx, "v2").Bool(), true)
|
||||
t.AssertEQ(c.MustGet(ctx, "v3").Bool(), false)
|
||||
|
||||
t.AssertEQ(c.Contains("v1"), true)
|
||||
t.AssertEQ(c.Contains("v2"), true)
|
||||
t.AssertEQ(c.Contains("v3"), true)
|
||||
t.AssertEQ(c.Contains("v4"), true)
|
||||
t.AssertEQ(c.Contains("v5"), false)
|
||||
|
||||
t.AssertEQ(c.GetInts("array"), []int{1, 2, 3})
|
||||
t.AssertEQ(c.GetStrings("array"), []string{"1", "2", "3"})
|
||||
t.AssertEQ(c.GetArray("array"), []interface{}{1, 2, 3})
|
||||
t.AssertEQ(c.GetInterfaces("array"), []interface{}{1, 2, 3})
|
||||
t.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
t.AssertEQ(c.MustGet(ctx, "array").Ints(), []int{1, 2, 3})
|
||||
t.AssertEQ(c.MustGet(ctx, "array").Strings(), []string{"1", "2", "3"})
|
||||
t.AssertEQ(c.MustGet(ctx, "array").Interfaces(), []interface{}{1, 2, 3})
|
||||
t.AssertEQ(c.MustGet(ctx, "redis").Map(), map[string]interface{}{
|
||||
"disk": "127.0.0.1:6379,0",
|
||||
"cache": "127.0.0.1:6379,1",
|
||||
})
|
||||
@ -229,67 +145,7 @@ func Test_SetFileName(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestCfg_New(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
os.Setenv("GF_GCFG_PATH", "config")
|
||||
c := gcfg.New("config.yml")
|
||||
t.Assert(c.Get("name"), nil)
|
||||
t.Assert(c.GetFileName(), "config.yml")
|
||||
|
||||
configPath := gfile.Pwd() + gfile.Separator + "config"
|
||||
_ = gfile.Mkdir(configPath)
|
||||
defer gfile.Remove(configPath)
|
||||
|
||||
c = gcfg.New("config.yml")
|
||||
t.Assert(c.Get("name"), nil)
|
||||
|
||||
_ = os.Unsetenv("GF_GCFG_PATH")
|
||||
c = gcfg.New("config.yml")
|
||||
t.Assert(c.Get("name"), nil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCfg_SetPath(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c := gcfg.New("config.yml")
|
||||
err := c.SetPath("tmp")
|
||||
t.AssertNE(err, nil)
|
||||
err = c.SetPath("gcfg.go")
|
||||
t.AssertNE(err, nil)
|
||||
t.Assert(c.Get("name"), nil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCfg_SetViolenceCheck(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c := gcfg.New("config.yml")
|
||||
c.SetViolenceCheck(true)
|
||||
t.Assert(c.Get("name"), nil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCfg_AddPath(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c := gcfg.New("config.yml")
|
||||
err := c.AddPath("tmp")
|
||||
t.AssertNE(err, nil)
|
||||
err = c.AddPath("gcfg.go")
|
||||
t.AssertNE(err, nil)
|
||||
t.Assert(c.Get("name"), nil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCfg_FilePath(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c := gcfg.New("config.yml")
|
||||
path, _ := c.GetFilePath("tmp")
|
||||
t.Assert(path, "")
|
||||
path, _ = c.GetFilePath("tmp")
|
||||
t.Assert(path, "")
|
||||
})
|
||||
}
|
||||
|
||||
func TestCfg_et(t *testing.T) {
|
||||
func TestCfg_Set(t *testing.T) {
|
||||
config := `log-path = "logs"`
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
path := gcfg.DefaultConfigFile
|
||||
@ -297,16 +153,18 @@ func TestCfg_et(t *testing.T) {
|
||||
t.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
|
||||
c := gcfg.New()
|
||||
t.Assert(c.Get("log-path"), "logs")
|
||||
adapterFile, err := gcfg.NewAdapterFile()
|
||||
t.AssertNil(err)
|
||||
t.Assert(adapterFile.MustGet(ctx, "log-path"), "logs")
|
||||
|
||||
err = c.Set("log-path", "custom-logs")
|
||||
c := gcfg.NewWithAdapter(adapterFile)
|
||||
c.Set(ctx, "log-path", "custom-logs")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(c.Get("log-path"), "custom-logs")
|
||||
t.Assert(c.MustGet(ctx, "log-path"), "custom-logs")
|
||||
})
|
||||
}
|
||||
|
||||
func TestCfg_Get(t *testing.T) {
|
||||
func TestCfg_Get_WrongConfigFile(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var err error
|
||||
configPath := gfile.TempDir(gtime.TimestampNanoStr())
|
||||
@ -323,82 +181,13 @@ func TestCfg_Get(t *testing.T) {
|
||||
"wrong config",
|
||||
)
|
||||
t.Assert(err, nil)
|
||||
c := gcfg.New("config.yml")
|
||||
t.Assert(c.Get("name"), nil)
|
||||
t.Assert(c.GetVar("name").Val(), nil)
|
||||
t.Assert(c.Contains("name"), false)
|
||||
t.Assert(c.GetMap("name"), nil)
|
||||
t.Assert(c.GetArray("name"), nil)
|
||||
t.Assert(c.GetString("name"), "")
|
||||
t.Assert(c.GetStrings("name"), nil)
|
||||
t.Assert(c.GetInterfaces("name"), nil)
|
||||
t.Assert(c.GetBool("name"), false)
|
||||
t.Assert(c.GetFloat32("name"), 0)
|
||||
t.Assert(c.GetFloat64("name"), 0)
|
||||
t.Assert(c.GetFloats("name"), nil)
|
||||
t.Assert(c.GetInt("name"), 0)
|
||||
t.Assert(c.GetInt8("name"), 0)
|
||||
t.Assert(c.GetInt16("name"), 0)
|
||||
t.Assert(c.GetInt32("name"), 0)
|
||||
t.Assert(c.GetInt64("name"), 0)
|
||||
t.Assert(c.GetInts("name"), nil)
|
||||
t.Assert(c.GetUint("name"), 0)
|
||||
t.Assert(c.GetUint8("name"), 0)
|
||||
t.Assert(c.GetUint16("name"), 0)
|
||||
t.Assert(c.GetUint32("name"), 0)
|
||||
t.Assert(c.GetUint64("name"), 0)
|
||||
t.Assert(c.GetTime("name").Format("2006-01-02"), "0001-01-01")
|
||||
t.Assert(c.GetGTime("name"), nil)
|
||||
t.Assert(c.GetDuration("name").String(), "0s")
|
||||
name := struct {
|
||||
Name string
|
||||
}{}
|
||||
t.Assert(c.GetStruct("name", &name) == nil, false)
|
||||
adapterFile, err := gcfg.NewAdapterFile("config.yml")
|
||||
t.AssertNil(err)
|
||||
|
||||
c.Clear()
|
||||
|
||||
arr, _ := gjson.Encode(
|
||||
g.Map{
|
||||
"name": "gf",
|
||||
"time": "2019-06-12",
|
||||
"person": g.Map{"name": "gf"},
|
||||
"floats": g.Slice{1, 2, 3},
|
||||
},
|
||||
)
|
||||
err = gfile.PutBytes(
|
||||
gfile.Join(configPath, "config.yml"),
|
||||
arr,
|
||||
)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(c.GetTime("time").Format("2006-01-02"), "2019-06-12")
|
||||
t.Assert(c.GetGTime("time").Format("Y-m-d"), "2019-06-12")
|
||||
t.Assert(c.GetDuration("time").String(), "0s")
|
||||
|
||||
err = c.GetStruct("person", &name)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(name.Name, "gf")
|
||||
t.Assert(c.GetFloats("floats") == nil, false)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCfg_Config(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
gcfg.SetContent("gf", "config.yml")
|
||||
t.Assert(gcfg.GetContent("config.yml"), "gf")
|
||||
gcfg.SetContent("gf1", "config.yml")
|
||||
t.Assert(gcfg.GetContent("config.yml"), "gf1")
|
||||
gcfg.RemoveContent("config.yml")
|
||||
gcfg.ClearContent()
|
||||
t.Assert(gcfg.GetContent("name"), "")
|
||||
})
|
||||
}
|
||||
|
||||
func TestCfg_With_UTF8_BOM(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
cfg := g.Cfg("test-cfg-with-utf8-bom")
|
||||
t.Assert(cfg.SetPath("testdata"), nil)
|
||||
cfg.SetFileName("cfg-with-utf8-bom.toml")
|
||||
t.Assert(cfg.GetInt("test.testInt"), 1)
|
||||
t.Assert(cfg.GetString("test.testStr"), "test")
|
||||
c := gcfg.NewWithAdapter(adapterFile)
|
||||
v, err := c.Get(ctx, "name")
|
||||
t.AssertNE(err, nil)
|
||||
t.Assert(v, nil)
|
||||
adapterFile.Clear()
|
||||
})
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
package gcfg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/container/gmap"
|
||||
"github.com/gogf/gf/debug/gdebug"
|
||||
"github.com/gogf/gf/os/genv"
|
||||
@ -17,6 +18,10 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx = context.TODO()
|
||||
)
|
||||
|
||||
func Test_Instance_Basic(t *testing.T) {
|
||||
config := `
|
||||
array = [1.0, 2.0, 3.0]
|
||||
@ -39,45 +44,8 @@ v4 = "1.234"
|
||||
}()
|
||||
|
||||
c := Instance()
|
||||
t.Assert(c.Get("v1"), 1)
|
||||
t.AssertEQ(c.GetInt("v1"), 1)
|
||||
t.AssertEQ(c.GetInt8("v1"), int8(1))
|
||||
t.AssertEQ(c.GetInt16("v1"), int16(1))
|
||||
t.AssertEQ(c.GetInt32("v1"), int32(1))
|
||||
t.AssertEQ(c.GetInt64("v1"), int64(1))
|
||||
t.AssertEQ(c.GetUint("v1"), uint(1))
|
||||
t.AssertEQ(c.GetUint8("v1"), uint8(1))
|
||||
t.AssertEQ(c.GetUint16("v1"), uint16(1))
|
||||
t.AssertEQ(c.GetUint32("v1"), uint32(1))
|
||||
t.AssertEQ(c.GetUint64("v1"), uint64(1))
|
||||
|
||||
t.AssertEQ(c.GetVar("v1").String(), "1")
|
||||
t.AssertEQ(c.GetVar("v1").Bool(), true)
|
||||
t.AssertEQ(c.GetVar("v2").String(), "true")
|
||||
t.AssertEQ(c.GetVar("v2").Bool(), true)
|
||||
|
||||
t.AssertEQ(c.GetString("v1"), "1")
|
||||
t.AssertEQ(c.GetFloat32("v4"), float32(1.234))
|
||||
t.AssertEQ(c.GetFloat64("v4"), float64(1.234))
|
||||
t.AssertEQ(c.GetString("v2"), "true")
|
||||
t.AssertEQ(c.GetBool("v2"), true)
|
||||
t.AssertEQ(c.GetBool("v3"), false)
|
||||
|
||||
t.AssertEQ(c.Contains("v1"), true)
|
||||
t.AssertEQ(c.Contains("v2"), true)
|
||||
t.AssertEQ(c.Contains("v3"), true)
|
||||
t.AssertEQ(c.Contains("v4"), true)
|
||||
t.AssertEQ(c.Contains("v5"), false)
|
||||
|
||||
t.AssertEQ(c.GetInts("array"), []int{1, 2, 3})
|
||||
t.AssertEQ(c.GetStrings("array"), []string{"1", "2", "3"})
|
||||
t.AssertEQ(c.GetArray("array"), []interface{}{1, 2, 3})
|
||||
t.AssertEQ(c.GetInterfaces("array"), []interface{}{1, 2, 3})
|
||||
t.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
"disk": "127.0.0.1:6379,0",
|
||||
"cache": "127.0.0.1:6379,1",
|
||||
})
|
||||
filepath, _ := c.GetFilePath()
|
||||
t.Assert(c.MustGet(ctx, "v1"), 1)
|
||||
filepath, _ := c.GetAdapter().(*AdapterFile).GetFilePath()
|
||||
t.AssertEQ(filepath, gfile.Pwd()+gfile.Separator+path)
|
||||
})
|
||||
}
|
||||
@ -92,28 +60,28 @@ func Test_Instance_AutoLocateConfigFile(t *testing.T) {
|
||||
t.AssertNil(gfile.Chdir(gdebug.TestDataPath()))
|
||||
defer gfile.Chdir(pwd)
|
||||
t.Assert(Instance("c1") != nil, true)
|
||||
t.Assert(Instance("c1").Get("my-config"), "1")
|
||||
t.Assert(Instance("folder1/c1").Get("my-config"), "2")
|
||||
t.Assert(Instance("c1").MustGet(ctx, "my-config"), "1")
|
||||
t.Assert(Instance("folder1/c1").MustGet(ctx, "my-config"), "2")
|
||||
})
|
||||
// Automatically locate the configuration file with supported file extensions.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
pwd := gfile.Pwd()
|
||||
t.AssertNil(gfile.Chdir(gdebug.TestDataPath("folder1")))
|
||||
defer gfile.Chdir(pwd)
|
||||
t.Assert(Instance("c2").Get("my-config"), 2)
|
||||
t.Assert(Instance("c2").MustGet(ctx, "my-config"), 2)
|
||||
})
|
||||
// Default configuration file.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
instances.Clear()
|
||||
localInstances.Clear()
|
||||
pwd := gfile.Pwd()
|
||||
t.AssertNil(gfile.Chdir(gdebug.TestDataPath("default")))
|
||||
defer gfile.Chdir(pwd)
|
||||
t.Assert(Instance().Get("my-config"), 1)
|
||||
t.Assert(Instance().MustGet(ctx, "my-config"), 1)
|
||||
|
||||
instances.Clear()
|
||||
localInstances.Clear()
|
||||
t.AssertNil(genv.Set("GF_GCFG_FILE", "config.json"))
|
||||
defer genv.Set("GF_GCFG_FILE", "")
|
||||
t.Assert(Instance().Get("my-config"), 2)
|
||||
t.Assert(Instance().MustGet(ctx, "my-config"), 2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -122,9 +90,9 @@ func Test_Instance_EnvPath(t *testing.T) {
|
||||
genv.Set("GF_GCFG_PATH", gdebug.TestDataPath("envpath"))
|
||||
defer genv.Set("GF_GCFG_PATH", "")
|
||||
t.Assert(Instance("c3") != nil, true)
|
||||
t.Assert(Instance("c3").Get("my-config"), "3")
|
||||
t.Assert(Instance("c4").Get("my-config"), "4")
|
||||
instances = gmap.NewStrAnyMap(true)
|
||||
t.Assert(Instance("c3").MustGet(ctx, "my-config"), "3")
|
||||
t.Assert(Instance("c4").MustGet(ctx, "my-config"), "4")
|
||||
localInstances = gmap.NewStrAnyMap(true)
|
||||
})
|
||||
}
|
||||
|
||||
@ -134,7 +102,7 @@ func Test_Instance_EnvFile(t *testing.T) {
|
||||
defer genv.Set("GF_GCFG_PATH", "")
|
||||
genv.Set("GF_GCFG_FILE", "c6.json")
|
||||
defer genv.Set("GF_GCFG_FILE", "")
|
||||
t.Assert(Instance().Get("my-config"), "6")
|
||||
instances = gmap.NewStrAnyMap(true)
|
||||
t.Assert(Instance().MustGet(ctx, "my-config"), "6")
|
||||
localInstances = gmap.NewStrAnyMap(true)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user