0

I have a runtime config instance that I need in other parts of the app, but it can only be created in main(). Ideally I would like to avoid using global variables.

// 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
}

Currently it's impossible to create anonymous util functions that could really benefit from having access to certain config variables. If the variables were basic types (like a string or int), I would probably just hard-code them in. However, a field like dbInstance requires a specific instance of a connected database.

robinnnnn
  • 1,675
  • 4
  • 17
  • 32

2 Answers2

0

This looks to me like a use case for the singleton pattern: your RuntimeConfig is a structure that should be initialized, exactly one instance of it should exist, and it should be possible to access it.

Community
  • 1
  • 1
Zoyd
  • 3,449
  • 1
  • 18
  • 27
0

Create configuration package with private variable and public functions (pseudo code):

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
}

Then in your main.go initialize config:

func main() {
    config, err := configuration.NewConfig(FlagsParameters)
    // use this config variable in main package
}

In other packages use:

config := configuration.Config()

As an alternative, you can implement singleton pattern (but I like it less)

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
}
Alexander R.
  • 1,756
  • 12
  • 19