83 lines
1.5 KiB
Go
83 lines
1.5 KiB
Go
package dotenv
|
|
|
|
import (
|
|
"errors"
|
|
"log/slog"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Assign env tag matching values from envMap
|
|
func Assign[T any](c *T, envMap map[string]string) error {
|
|
if c == nil {
|
|
return errors.New("nil arg")
|
|
}
|
|
|
|
slog.Info("env map", "v", envMap)
|
|
|
|
val := reflect.Indirect(reflect.ValueOf(c))
|
|
name := val.Type().Name()
|
|
for i := range val.NumField() {
|
|
f := val.Type().Field(i)
|
|
tag := f.Tag.Get("env")
|
|
if tag == "" {
|
|
continue
|
|
}
|
|
|
|
var v string
|
|
var ok bool
|
|
if multiTag := strings.Split(tag, ","); len(multiTag) > 1 {
|
|
// multi tags like env:"DB_URL,PG_DB_URL"
|
|
for _, mt := range multiTag {
|
|
if v, ok = envMap[strings.TrimSpace(mt)]; ok {
|
|
break
|
|
}
|
|
}
|
|
} else {
|
|
v, ok = envMap[tag]
|
|
}
|
|
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
field := val.FieldByName(f.Name)
|
|
if !field.IsValid() {
|
|
continue
|
|
}
|
|
|
|
switch f.Type.Kind() {
|
|
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
|
if v, err := strconv.ParseInt(v, 10, 64); err != nil {
|
|
return err
|
|
} else {
|
|
field.SetInt(v)
|
|
}
|
|
case reflect.Float32, reflect.Float64:
|
|
if v, err := strconv.ParseFloat(v, 10); err != nil {
|
|
return err
|
|
} else {
|
|
field.SetFloat(v)
|
|
}
|
|
case reflect.Bool:
|
|
if strings.EqualFold(v, "true") {
|
|
field.SetBool(true)
|
|
} else {
|
|
field.SetBool(false)
|
|
}
|
|
|
|
default:
|
|
field.SetString(v)
|
|
}
|
|
|
|
if name == "" {
|
|
slog.Info("override value from env", "field", f.Name)
|
|
} else {
|
|
slog.Info("override value from env", "type", name, "field", f.Name)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|