package main import ( "errors" "os" "reflect" "strconv" "strings" ) func getEnv(mask interface{}) Env { r := reflect.ValueOf(mask) argTypeRV := reflect.New(r.Type()) for i := 0; i < r.NumField(); i++ { v := r.Type().Field(i).Tag.Get("env") d := r.Type().Field(i).Tag.Get("default") env, ok := os.LookupEnv(v) var val string if ok { val = env } else { val = d } switch t := r.Type().Field(i).Type.Name(); t { case "string": argTypeRV.Elem().Field(i).SetString(val) case "bool": if strings.EqualFold(val, "true") { argTypeRV.Elem().Field(i).SetBool(true) } else { argTypeRV.Elem().Field(i).SetBool(false) } case "uint64": num, err := strconv.ParseUint(val, 10, 64) if err != nil { panic(err) } argTypeRV.Elem().Field(i).SetUint(num) default: panic(errors.New("Something strange happened: " + t)) } } return argTypeRV.Elem().Interface().(Env) }