2 files changed,
124 insertions(+),
0 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2025-12-04 16:28:05 +0200
Authored at:
2025-12-04 16:12:18 +0200
Change ID:
nllmpxvquqywxpvyollnpuzxtvwnzprt
Parent:
8cb64b3
jump to
| A | envy/env.go |
| A | envy/env_test.go |
A
envy/env.go
··· 1 +package envy 2 + 3 +import ( 4 + "os" 5 + "strconv" 6 + "time" 7 +) 8 + 9 +func Get[T comparable](key string) T { 10 + var zero T 11 + val, ok := os.LookupEnv(key) 12 + if !ok { 13 + return zero 14 + } 15 + 16 + var res any 17 + switch any(zero).(type) { 18 + case string: 19 + res = val 20 + case int: 21 + if n, err := strconv.Atoi(val); err == nil { 22 + res = n 23 + } 24 + case int64: 25 + if n, err := strconv.ParseInt(val, 10, 64); err == nil { 26 + res = n 27 + } 28 + case float64: 29 + if f, err := strconv.ParseFloat(val, 64); err == nil { 30 + res = f 31 + } 32 + case bool: 33 + if b, err := strconv.ParseBool(val); err == nil { 34 + res = b 35 + } 36 + case time.Duration: 37 + if d, err := time.ParseDuration(val); err == nil { 38 + res = d 39 + } 40 + } 41 + return res.(T) 42 +} 43 + 44 +func GetOrDefault[T comparable](key string, def T) T { 45 + var zero T 46 + if val := Get[T](key); val != zero { 47 + return val 48 + } 49 + return def 50 +}
A
envy/env_test.go
··· 1 +package envy_test 2 + 3 +import ( 4 + "testing" 5 + "time" 6 + 7 + "olexsmir.xyz/x/envy" 8 + "olexsmir.xyz/x/is" 9 +) 10 + 11 +func TestGet(t *testing.T) { 12 + env := "TESTING" 13 + t.Run("string", func(t *testing.T) { 14 + t.Setenv(env, "asdf") 15 + is.Equal(t, "asdf", envy.Get[string](env)) 16 + }) 17 + t.Run("string, not set", func(t *testing.T) { 18 + is.Equal(t, "", envy.Get[string](env)) 19 + }) 20 + 21 + t.Run("int", func(t *testing.T) { 22 + t.Setenv("TESTING", "123") 23 + is.Equal(t, 123, envy.Get[int](env)) 24 + }) 25 + t.Run("int, not set", func(t *testing.T) { 26 + is.Equal(t, 0, envy.Get[int](env)) 27 + }) 28 + 29 + t.Run("int64", func(t *testing.T) { 30 + t.Setenv(env, "112233") 31 + is.Equal(t, 112233, envy.Get[int64](env)) 32 + }) 33 + t.Run("int64, not set", func(t *testing.T) { 34 + is.Equal(t, 0, envy.Get[int64](env)) 35 + }) 36 + 37 + t.Run("float64", func(t *testing.T) { 38 + t.Setenv(env, "123.123") 39 + is.Equal(t, 123.123, envy.Get[float64](env)) 40 + }) 41 + t.Run("float64, not set", func(t *testing.T) { 42 + is.Equal(t, 0, envy.Get[float64](env)) 43 + }) 44 + 45 + t.Run("bool", func(t *testing.T) { 46 + t.Setenv(env, "true") 47 + is.Equal(t, true, envy.Get[bool](env)) 48 + }) 49 + t.Run("bool, not set", func(t *testing.T) { 50 + is.Equal(t, false, envy.Get[bool](env)) 51 + }) 52 + 53 + t.Run("time.Duration", func(t *testing.T) { 54 + t.Setenv(env, "3s") 55 + got := envy.Get[time.Duration](env) 56 + is.Equal(t, 3*time.Second, got) 57 + }) 58 + t.Run("time.Duration, not set", func(t *testing.T) { 59 + got := envy.Get[time.Duration](env) 60 + is.Equal(t, 0, got) 61 + }) 62 +} 63 + 64 +func TestGetOrDefault(t *testing.T) { 65 + env := "TESTING" 66 + t.Run("string, unset", func(t *testing.T) { 67 + is.Equal(t, "asdf", envy.GetOrDefault(env, "asdf")) 68 + }) 69 + 70 + t.Run("string, unset", func(t *testing.T) { 71 + t.Setenv(env, "test") 72 + is.Equal(t, "test", envy.GetOrDefault(env, "asdf")) 73 + }) 74 +}