Simple configuration on Go

Very often your new tool/service needs to have a configuration defined either via parameters or configuration file.
For example, you want to have different settings in development and production environments, or you just have a separate fleets for different clients.

It is pretty easy to add configuration support to you Go application using YAML for configurations and gopkg.in/yaml.v2 for deserializing YAML files into struct value.

Here is an example YAML configuration file. It contains service name and its listening endpoint, and also database connection URL. Pretty simple!
# Service name and address to listen
service:
name: AccountService
address: 127.0.0.1:12020
# DBs to connect to, storing password is OK for local DEV database
db:
accounts: postgres://192.168.99.100:32768/accounts?user=ABC&password=XYZ&sslmode=disable
view raw config.dev.yaml hosted with ❤ by GitHub

To read configuration, we first open and read whole configuration file, and then use yaml package to unmarshal it into value of Configuration type.
import "gopkg.in/yaml.v2"
// Configuration object that stores all configuration data
type Configuration struct {
Db DbConfiguration
Service ServiceConfiguration
}
// Database configuration
type DbConfiguration struct {
Accounts string
}
// Service configuration
type ServiceConfiguration struct {
Name string
Address string
}
// LoadConfiguration loads configuration from specified file
func LoadConfiguration(configFilePath string) (*Configuration, error) {
file, err := os.Open(configFilePath)
if err != nil {
return nil, fmt.Errorf("failed to load file %s: %s", configFilePath, err)
}
data, err := ioutil.ReadAll(file)
if err != nil {
return nil, fmt.Errorf("failed to read file %s: %s", configFilePath, err)
}
configuration := &Configuration{}
err = yaml.Unmarshal(data, configuration)
if err != nil {
return nil, fmt.Errorf("failed to parse yaml file %s: %s", configFilePath, err)
}
return configuration, nil
}
view raw config.go hosted with ❤ by GitHub

And finally a part of main function in our application, where we use parameter to pass a path to the configuration file, and load it to use configuration later:
package main
import (
"flag"
"log"
)
var configFile = flag.String("config", "", "path to the configuration file")
func main() {
flag.Parse()
// load configuration
configuration, err := config.LoadConfiguration(*configFile)
if err != nil {
log.Fatalf("failed to read configuration file: %s", err)
}
// now can use `configuration` value
}
view raw main.go hosted with ❤ by GitHub

That's it. Simple and fast!

Reinforcing feedback loops

There are two different types of feedback loops recognized in systems:
  1. Balancing feedback loops
  2. Reinforcing feedback loops
Balancing feedback loop controls inflow and outflow of resources. Example of it would be amount of money on the bank account. Amount increases if you put money into, and decreases if you withdraw them.

Reinforcing feedback loop is a different kind of animal. It isn't as strait forward as balancing feedback loop. Example of it would be interest rate for the bank account. The more you have money, the larger interest you get. The larger interest you get, the more money on you bank account you have. Another example of reinforcing feedback loop would be well know dependency between education and social status: if you have money, you can get better education, the better education you have, the more you can earn etc.

Many people are very focused on balancing feedback loops and give little attention to reinforcement feedback loops. At the same time latter one are very important in our life.

Reinforcing feedback loops are very important in our life. They can allow fast growth or decay. They are that magic behind growth of many successful companies.

The better Google's search is, the more people use it. The more people use it, the more data Google has to improve its search.

The better apps on your iPhone, the more you use it. The more you use it, the better apps are becoming. The better apps, the more you use iPhone. Similar thing with AppStore.

The more you invest into some company XTZ, they more money it would have. The more money they have, the more successful they are. The more successful they are, the more stock growths. The more stock growths, the more chances you keep investing.

And so many and many examples.

Reinforcement feedback loop is one behind "Success for successful and fail for failures" trap.

Thus, creating successful enterprise is not only about good old balancing feedback loop. It is always a lot about reinforcing feedback loop behind it.

Wonderful book on this:
Thinking in Systems: A Primer

See it on Goodreads







Links:
  • http://www.systems-thinking.org/theWay/sre/re.htm
  • https://www.youtube.com/watch?v=hdGxIameiM8