kelseyhightower / envconfig

Golang library for managing configuration data from environment variables
MIT License
5.01k stars 377 forks source link

Strange behaviour #155

Closed steadysupply closed 4 years ago

steadysupply commented 4 years ago

Hello,

This library looks handy, but doesn't behave as I expect. I've prepared a small code example that illustrates the behaviour that I am confused about.

// env.go
package main
import (
        "fmt"
        "os"
        "log"
        "github.com/kelseyhightower/envconfig"
)

type config struct {
        setting_a       string  `envconfig:"SETTING_A"`
        setting_b       string  `envconfig:"SETTING_B"  required:"true"`
        setting_c       string  `envconfig:"SETTING_C"  required:"true"`

        Setting_a       string  `envconfig:"SETTING_A"`
        Setting_b       string  `envconfig:"SETTING_B"  required:"true"`
        Setting_c       string  `envconfig:"SETTING_C"  required:"true"`
}

func main(){
        var c config
        err := envconfig.Process("n/a", &c)
        if err != nil { log.Fatal(err) }
    fmt_str := `
envconfig says
--------------
setting_a: %s
setting_b: %s
setting_c: %s

Setting_a: %s
Setting_b: %s
Setting_c: %s

os.Getenv says
--------------
SETTING_A: %s
SETTING_B: %s
SETTING_C: %s

`
        fmt.Printf(
        fmt_str,
        c.setting_a, c.setting_b, c.setting_c,
        c.Setting_a, c.Setting_b, c.Setting_c,
        os.Getenv("SETTING_A"), os.Getenv("SETTING_B"), os.Getenv("SETTING_C"),
    )
}

Invoking the the above with some environment set gives

$ SETTING_A=A SETTING_B=B go run env.go

envconfig says
--------------
setting_a: 
setting_b: 
setting_c: 

Setting_a: A
Setting_b: B
Setting_c: 

os.Getenv says
--------------
SETTING_A: A
SETTING_B: B
SETTING_C: 

Two things that I expect to happen in the above situation are a) setting_a and setting_b fields are populated with the corresponding SETTING_A and SETTING_B strings from the environment and b) Process returns an error because SETTING_C is not present in the environment (either because setting_c or Setting_c fields mandate it to be).

The programme above shows that neither a) nor b) happen. I understand there are conventions related to uppercasing the first characters of struct fields in Go, but shouldn't an error be returned by Process because of a missing required key?

Cheers,

Ben

dotSlashLu commented 4 years ago

Hi, @steadysupply. I think situation a is actually expected. Struct keys with lowercase initials are private thus are not settable by another library.

steadysupply commented 4 years ago

You're quite right.