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  }