diff --git a/.golangci.yml b/.golangci.yml index b9f4356..a353259 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -15,3 +15,4 @@ linters: - wsl - gofumpt - gosec + - nlreturn \ No newline at end of file diff --git a/hw08_zenv_to_structure/README.md b/hw08_zenv_to_structure/README.md new file mode 100644 index 0000000..7ff272d --- /dev/null +++ b/hw08_zenv_to_structure/README.md @@ -0,0 +1,3 @@ +## Домашнее задание №8_1 «Рефлексия» + +Реализовать функцию, заполняющую структуру значениями из переменных окружения. diff --git a/hw08_zenv_to_structure/env_to_struct.go b/hw08_zenv_to_structure/env_to_struct.go new file mode 100644 index 0000000..737028d --- /dev/null +++ b/hw08_zenv_to_structure/env_to_struct.go @@ -0,0 +1,57 @@ +package hw08_zenv_to_structure //nolint:golint,stylecheck +import ( + "fmt" + "log" + "os" + "reflect" + "strconv" + "strings" +) + +func Slice2struct(mp []string, str interface{}) error { + v := reflect.ValueOf(str) + if v.Kind() != reflect.Ptr { + return fmt.Errorf("%T is not a pointer", str) + } + v = v.Elem() + if v.Kind() != reflect.Struct { + return fmt.Errorf("%T is not a pointer to struct", str) + } + + for _, e := range mp { + st := strings.Split(e, "=") + var key string = st[0] + var value interface{} = st[1] + f := v.FieldByName(key) + if f.IsValid() && f.CanSet() { + switch v := f.Interface().(type) { + case int: + val, err := strconv.Atoi(value.(string)) + if err != nil { + return err + } + x := int64(val) + if !f.OverflowInt(x) { + f.SetInt(x) + } + case string: + f.SetString(value.(string)) + case bool: + f.SetBool(value.(string) == "true") + case []interface{}: + input := reflect.ValueOf(value) + f.Set(input) + default: + return fmt.Errorf("i don't know how to parse type %T", v) + } + } + } + return nil +} + +func Env2struct(s interface{}) { + env := os.Environ() + if err := Slice2struct(env, s); err != nil { + log.Fatal("ошибка", err.Error()) + } +} diff --git a/hw08_zenv_to_structure/env_to_struct_test.go b/hw08_zenv_to_structure/env_to_struct_test.go new file mode 100644 index 0000000..7944807 --- /dev/null +++ b/hw08_zenv_to_structure/env_to_struct_test.go @@ -0,0 +1,46 @@ +package hw08_zenv_to_structure + +import ( + "github.com/stretchr/testify/require" + "log" + "os" + "testing" +) + +func TestSlice2struct(t *testing.T) { + mp := []string{"ENV1=fsfsdvsvssdfsd fsf fsf sds", "ENV2=12345", "ENV3=aefrsgrgdtgtdhn"} + var st struct { + ENV1 string + ENV2 int + ENV3 string + } + err := Slice2struct(mp, &st) + require.Equal(t, struct { + ENV1 string + ENV2 int + ENV3 string + }{"fsfsdvsvssdfsd fsf fsf sds", 12345, "aefrsgrgdtgtdhn"}, st) + require.NoError(t, err) +} + +func TestEnv2struct(t *testing.T) { + type env struct { + ENV1 string + ENV2 bool + ENV3 int + } + exp := env{"какая-то строка", true, 1234567} + if os.Setenv("ENV1", "какая-то строка") != nil { + log.Fatal("не удалось установить ENV") + } + if os.Setenv("ENV2", "true") != nil { + log.Fatal("не удалось установить ENV") + } + if os.Setenv("ENV3", "1234567") != nil { + log.Fatal("не удалось установить ENV") + } + + var res env + Env2struct(&res) + require.Equal(t, exp, res) +} diff --git a/hw08_zenv_to_structure/go.mod b/hw08_zenv_to_structure/go.mod new file mode 100644 index 0000000..00d66d4 --- /dev/null +++ b/hw08_zenv_to_structure/go.mod @@ -0,0 +1,8 @@ +module hw08_zenv_to_structure + +go 1.14 + +require ( + github.com/Ompluscator/dynamic-struct v1.2.0 + github.com/stretchr/testify v1.6.1 +)