Configuration can be done on a lot of different manners. This is the pattern I like the most, and gives me all the flexibility I'd need.
There are a lot of configuration file formats, just to mention a few:
The Yaml format is my preferred option. Toml is nice, but isn't really common yet, and it should be easy to update the configuration file. JSON is my least favourite option, because in my opinion it is merely a transport format and not a configuration format.
Each application should have a default configuration set. This will make sure that the application is being configured right and secure, and allows the application to be started directly. It also allows you to introduce new options during updates without breaking old installations. Remember, the time you updated a service and it would'nt start because of new configuration settings?
Default configuration should be overwritten by the settings in the configuration file.
Configuration should be strongly typed, a map[string]interface is way too easy and you're certain to introduce bugs because of different typed configuration keys.
It should be possible to extend the configuration with methods.
- the file defines all possible structs
- all default settings will be set in DefaultConfig
- when things needs to be loaded, the config file can be extended with methods (like PrivateKey()) in the appropriate section
- Load() will load the config.yaml
- Load() will merge the DefaultConfig and overwrite its settings
This will load the config, for example in the main. It will just initiate a new instance of Config and load the file.