Preflight Checklist
- [X] I have searched the issue tracker for an issue that matches the one I want to file, without success.
- [X] I am not looking for support or already pursued the available support channels without success.
- [X] I have checked the troubleshooting guide for my problem, without success.
Viper Version
v1.15.0
Go Version
go1.18.7
Config Source
Environment variables, Files
Format
YAML
Repl.it link
https://replit.com/@vt128/Viper-bind-bug#repro.sh
Code reproducing the issue
Here's the code to repro the issue:
Struct to hold the config:
type Module struct {
Enabled bool
Target uint
Name string
}
type ConfigSchema struct {
Module Module
}
The corresponding config file:
```yaml
token: "local"
module:
enabled: 1
target: 42
name: yes
module.target: 52
The code to read the config:
// Set config path
rp, err := os.UserHomeDir()
if err != nil {
log.Fatalw("Failed to get user home directory", "error", err)
}
viper.AddConfigPath(".")
viper.AddConfigPath(rp)
viper.SetConfigType("yaml")
viper.SetConfigName("setting")
// Set env
viper.AutomaticEnv()
replacer := strings.NewReplacer("-", "_")
viper.SetEnvKeyReplacer(replacer)
viper.SetEnvPrefix("app")
viper.BindEnv("token", "TEST")
err = viper.BindEnv("module.target", "TARGET", "MOD")
if err != nil {
log.Fatalw("Failed to bind env", "error", err)
}
// for default value
viper.SetDefault("Module", Module{
Enabled: true,
Target: 100,
Name: "default",
})
// Read config file
var C ConfigSchema
if err := viper.ReadInConfig(); err != nil {
log.Fatalw("Failed to read config", "error", err)
}
// Parse config
if err := viper.Unmarshal(&C); err != nil {
log.Fatalw("Failed to unmarshal config", "error", err)
}
all := viper.AllSettings()
Expected Behavior
Run TARGET=8080 ./main
, C.Module.Target
and all.module.target
are always 8080 consistently
Actual Behavior
I got the following inconsistent results:
- 40-50% of the time, the
C.Module.Target
is 42, not 8080 from the env - While
C.Module.Target
is 42,all.module.target
may be 8080 or 42, the possibility is 50-50 - For the rest, the bind env works, and
C.Module.Target
andall.module.target
are 8080
If the viper.SetDefault("Module", ...)
is removed, the bind env works consistently, i.e. C.Module.Target
and all.module.target
were always 8080.
Steps To Reproduce
The command to run for 1000 times:
for x in $(seq 1 1000); do TARGET=8080 ./main; done
In Repl.it link -- just run the ./repro.sh
, it repeats for 100 times.
Additional Information
No response
Comment From: github-actions[bot]
👋 Thanks for reporting!
A maintainer will take a look at your issue shortly. 👀
In the meantime: We are working on Viper v2 and we would love to hear your thoughts about what you like or don't like about Viper, so we can improve or fix those issues.
⏰ If you have a couple minutes, please take some time and share your thoughts: https://forms.gle/R6faU74qPRPAzchZ9
📣 If you've already given us your feedback, you can still help by spreading the news, either by sharing the above link or telling people about this on Twitter:
https://twitter.com/sagikazarmark/status/1306904078967074816
Thank you! ❤️
Comment From: github-actions[bot]
Issues with no activity for 30 days are marked stale and subject to being closed.