github.com/shoshinnikita/budget-manager@v0.7.1-0.20220131195411-8c46ff1c6778/internal/pkg/env/env.go (about) 1 package env 2 3 import ( 4 "encoding" 5 "os" 6 "reflect" 7 "strconv" 8 9 "github.com/ShoshinNikita/budget-manager/internal/pkg/errors" 10 ) 11 12 func Load(key string, target interface{}) error { 13 envValue, ok := os.LookupEnv(key) 14 if !ok { 15 return nil 16 } 17 18 if u, ok := target.(encoding.TextUnmarshaler); ok { 19 return u.UnmarshalText([]byte(envValue)) 20 } 21 22 value := reflect.ValueOf(target) 23 if value.Kind() != reflect.Ptr { 24 return errors.New("target must be a pointer") 25 } 26 value = value.Elem() 27 if !value.CanSet() { 28 return errors.New("target can't be set") 29 } 30 31 wrapParseErr := func(err error) error { 32 return errors.Wrapf(err, "value for %q is invalid", key) 33 } 34 switch value.Kind() { 35 case reflect.Bool: 36 v, err := strconv.ParseBool(envValue) 37 if err != nil { 38 return wrapParseErr(err) 39 } 40 value.SetBool(v) 41 42 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 43 v, err := strconv.ParseInt(envValue, 10, 64) 44 if err != nil { 45 return wrapParseErr(err) 46 } 47 value.SetInt(v) 48 49 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 50 v, err := strconv.ParseUint(envValue, 10, 64) 51 if err != nil { 52 return wrapParseErr(err) 53 } 54 value.SetUint(v) 55 56 case reflect.Float32, reflect.Float64: 57 v, err := strconv.ParseFloat(envValue, 64) 58 if err != nil { 59 return wrapParseErr(err) 60 } 61 value.SetFloat(v) 62 63 case reflect.String: 64 value.SetString(envValue) 65 66 default: 67 return errors.Errorf("target of kind %q is not supported", value.Kind()) 68 } 69 70 return nil 71 }