我有一个在应用程序的其他部分中需要的运行时配置实例,但只能在main()中创建它。理想情况下,我想避免使用全局变量。
// main.go
type RuntimeConfig struct {
db *DatabaseInstance
app_name string
... etc ...
}
func main() {
dbInstance = ConnectToDB(...args) // returns *DatabaseInstance
runtimeConfig := *Config{
dbInstance,
"My app",
... etc ...
}
}
// elsewhere.go
func SomeUtilityFuncThatNeedsRuntime(i int) int {
runtime := GetRuntime() // imaginary, magical runtime getter
db := runtime.DatabaseInstance
appName := runtime.appName
db.Save(appName, db, ...)
return i + 1
}
当前,不可能创建匿名的util函数,这些功能实际上可以从访问某些配置变量中受益。如果变量是基本类型(例如字符串或int),我可能只是将它们硬编码。但是,诸如dbInstance
之类的字段需要连接的数据库的特定实例。
在我看来,这就像单身模式的用例:您的runtimeconfig是一个应该初始化的结构,应该存在一个实例,应该可以访问它。
使用私有变量和公共功能(伪代码)创建配置软件包:
package configuration
type Configuration struct {
}
var config *Configuration = nil
func GetConfig() *Configuration {
return config
}
func configLoad(filePath string) error {
config = new(Configuration)
// load your config from file, fill config structure
return nil
}
func NewConfig(flags models.ConfigFlags) (*Configuration, error) {
err := configLoad(flags.Flagconfiguration) // Path of config file.
if err != nil {
return nil, err
}
return config, nil
}
然后在您的Main.go初始化配置:
func main() {
config, err := configuration.NewConfig(FlagsParameters)
// use this config variable in main package
}
在其他软件包中使用:
config := configuration.Config()
作为替代方案,您可以实现单例模式(但我喜欢它少)
type Configuration struct {
}
var config *Configuration
var once sync.Once
func GetConfig() *Configuration {
once.Do(func() {
// init your config here. This code will executed once and thread safe
})
return config
}