From 6a345d96037884881e6c32d04e509712abea4b00 Mon Sep 17 00:00:00 2001 From: "Fabrizio (Misto) Milo" Date: Tue, 7 Oct 2014 18:07:50 -0700 Subject: [PATCH] feature: add support for time.Duration --- README.md | 11 ++++++----- env_test.go | 20 ++++++++++++++++++++ var.go | 18 ++++++++++++++++-- 3 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 env_test.go diff --git a/README.md b/README.md index 84f744e..e63e149 100644 --- a/README.md +++ b/README.md @@ -39,16 +39,17 @@ func main() { ``` -This library uses runtime reflection just like `encoding/json`. Most programs won't have more than a handful of config objects, so the slowness typically associated with reflection is negligible here. +This library uses runtime reflection just like `encoding/json`. Most programs won't have more than a handful of config objects, so the slowness typically associated with reflection is negligible here. ### Supported types -Four types are currently supported: +Four types are currently supported: * `string` - defaults to `""` * `int` - defaults to `0` * `bool` - defaults to `false` -* `float64` - defaults to `0.0` +* `float64` - defaults to `0.0` +* `time.Duration` - defaults to `0` Support for custom types via interfaces will likely make an an appearance at a later date. @@ -85,7 +86,7 @@ type Config struct { #### `default` -If specified, the default will be used if no environment variable is found matching the key. Default values must be castable to the associated struct field type, otherwise an error is returned. +If specified, the default will be used if no environment variable is found matching the key. Default values must be castable to the associated struct field type, otherwise an error is returned. ```go // Look for a variable `ENABLED` or otherwise default to true @@ -108,7 +109,7 @@ config := &Config{} fmt.Println(config.Name) // prints "Inigo" ``` -#### `options` +#### `options` Options ensure that an environment variable is in a set of possible valid values. If it is not, an error is returned. diff --git a/env_test.go b/env_test.go new file mode 100644 index 0000000..f00ffab --- /dev/null +++ b/env_test.go @@ -0,0 +1,20 @@ +package env + +import ( + "testing" + "time" +) + +func TestParseDuration(t *testing.T) { + var cfg = struct { + Duration time.Duration `env:"key=DURATION default=5s"` + }{} + + if err := Process(&cfg); err != nil { + t.Fatal(err) + } + + if cfg.Duration != time.Second*5 { + t.Fatalf("%v != %f ", cfg.Duration, time.Second*5) + } +} diff --git a/var.go b/var.go index e8f6b8e..66f8f21 100644 --- a/var.go +++ b/var.go @@ -7,6 +7,7 @@ import ( _ "regexp" "strconv" "strings" + "time" ) // Var struct @@ -22,11 +23,16 @@ type Var struct { // NewVar returns a new Var func NewVar(field reflect.StructField) (*Var, error) { + return NewVarWithFunc(field, os.Getenv) +} + +// NewVarWithFunc returns a new Var. get returns the value for the given key +func NewVarWithFunc(field reflect.StructField, get func(string) string) (*Var, error) { // spew.Dump(new(Var).Default == reflect.ValueOf(nil)) newVar := &Var{} //Default: reflect.ValueOf(nil)} newVar.Parse(field) - value, err := convert(newVar.Type, os.Getenv(newVar.Key)) + value, err := convert(newVar.Type, get(newVar.Key)) if err != nil { return newVar, err } @@ -168,6 +174,15 @@ func convert(t reflect.Type, value string) (reflect.Value, error) { return reflect.ValueOf(nil), nil } + var d time.Duration + + switch t { + case reflect.TypeOf(d): + result, err := time.ParseDuration(value) + return reflect.ValueOf(result), err + default: + } + switch t.Kind() { case reflect.String: return reflect.ValueOf(value), nil @@ -177,7 +192,6 @@ func convert(t reflect.Type, value string) (reflect.Value, error) { case reflect.Int: return parseInt(value) case reflect.Bool: - return parseBool(value) }