Settings and configurations for golang application
- Easy to learn and easy to use settings for golang libraries and applications.
- Settings object is represented as
map[string]interface{}
object.
- Settings can be marshalled to JSON or un-marshalled from JSON.
- Possible to add more formats for marshalling and un-marshalling settings.
- All methods exported on settings object are immutable, except
Mixin
.
- Stable APIs, existing APIs are not going to change.
Settings as Key value pairs
Golang map is the chosen structure for passing around settings, holding them
within components and interpret them when ever needed. To create new
settings object:
setts := make(Settings)
Subsequently setts
can be populated with {key,value} pairs, where each
{key,value} pair correspond to a single configuration parameter. To make
most out of Settings
it is better to avoid nested values, as in:
// not recommended
setts["llrb"] = Settings{
"maxkeylen": 1024,
"maxvallen": 1024,
}
Instead compose settings as:
// recommended
setts := make(Settings)
setts["llrb.maxkeylen"] = 1024
setts["llrb.maxvallen"] = 1024
Although the former style is quite natural to manage a tree of settings at
component and sub-component level, it can quickly become complex when
we start passing settings object around the application. While the later
style encourages flat map of {key,value} pairs, we can still preserve the
topology of settings by using the dot-separated namespaces. There are three
APIs available to filter out component level settings and merge it with
container namespace, Section
, Trim
, and AddPrefix
:
setts := make(Settings)
setts["numvbuckets"] = 8
setts["memalloc"] = 1000000
setts["llrb.maxkeylen"] = 1024
setts["llrb.maxvallen"] = 1024
llrbsetts := setts.Section("llrb.") // Section
setts.Section API will filter out setting keys that are prefixed by llrb.
,
it will look-like:
llrbsetts <==> Settings{"llrb.maxkeylen": 1024, "llrb.maxvallen": 1024}
While passing llrbsettings to the llrb component, it may not expect the
llrb.
prefixed to its settings key-name. To trim them away:
llrbsettings := setts.Section("llrb.").Trim("llrb.") // Trim away "llrb."
Now, llrbsettings will just be:
llrbsetts <==> Settings{"maxkeylen": 1024, "maxvallen": 1024}
In case, the llrb component is going to provide default set of
configuration parameters, and we want to merge them with our
application-level settings object, then, use AddPrefix:
appsetts := llrbsetts.AddPrefix("llrb.")
appsetts will look like:
appsetts <==> Settings{"llrb.maxkeylen": 1024, "llrb.maxvallen": 1024}
Settings from json
Most often, settings are obtained from JSON text. One of the reason for
using map[string]interface{}
as the underlying data-structure is to keep
it friendly for JSON. To initialize Settings from JSON:
var setts Settings
json.Unmarshal(data, &setts)
Can't get simpler than that !
Accessors
With map[string]interface{}
, settings value are resolved only during run
time. There are several helper functions that type check and extract the
settings value.
- Bool(key string), return the boolean value for key.
- Float64(key string), return the float64 value for key.
- Int64(key string) return the int64 value for key.
- Uint64(key string) return the uint64 value for key.
- String(key string) return the string value for key.
- Strings(key string) shall parse value as comma separated string items.
NOTE: To encode large numbers that can fit within int64 and uint64,
settings value can be encoded as decimal strings
Eg: {"epoch": "1125899906842624"}
.
Panic and Recovery
Settings API don't return error, instead it creates panic. This is because
settings are mostly part of bootstrapping process and are expected to be
clean and suggested by developers. If panics become un-avoidable please use
panic/recover. We are
listing some of the cases when panic can happened.
- When accessing a settings key which is not present in the map.
- When using one of the typed accessors, if underlying value does not match
the accessor type.
How to contribute
- Pick an issue, or create an new issue. Provide adequate documentation for
the issue.
- Assign the issue or get it assigned.
- Work on the code, once finished, raise a pull request.
- Gosettings is written in golang, hence expected to
follow the global guidelines for writing go programs.
- As of now, branch
master
is the development branch.