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

1.19

Go Version

1.21

Config Source

Files

Format

YAML, TOML

Repl.it link

No response

Code reproducing the issue

func Viper(path ...string) *viper.Viper {
var config string


if len(path) == 0 {
flag.StringVar(&config, "c", "", "choose config file.")
flag.Parse()
if config == "" { // 判断命令行参数是否为空
if configEnv := os.Getenv(internal.ConfigEnv); configEnv == "" { // 判断 internal.ConfigEnv 常量存储的环境变量是否为空
switch gin.Mode() {
case gin.DebugMode:
config = internal.ConfigDefaultFile
fmt.Printf("您正在使用gin模式的%s环境名称,config的路径为%s\n", gin.EnvGinMode, internal.ConfigDefaultFile)
case gin.ReleaseMode:
config = internal.ConfigReleaseFile
fmt.Printf("您正在使用gin模式的%s环境名称,config的路径为%s\n", gin.EnvGinMode, internal.ConfigReleaseFile)
case gin.TestMode:
config = internal.ConfigTestFile
fmt.Printf("您正在使用gin模式的%s环境名称,config的路径为%s\n", gin.EnvGinMode, internal.ConfigTestFile)
}
} else { // internal.ConfigEnv 常量存储的环境变量不为空 将值赋值于config
config = configEnv
fmt.Printf("您正在使用%s环境变量,config的路径为%s\n", internal.ConfigEnv, config)
}
} else { // 命令行参数不为空 将值赋值于config
fmt.Printf("您正在使用命令行的-c参数传递的值,config的路径为%s\n", config)
}
} else { // 函数传递的可变参数的第一个值赋值于config
config = path[0]
fmt.Printf("您正在使用func Viper()传递的值,config的路径为%s\n", config)
}


v := viper.New()
v.SetConfigFile(config)
v.SetConfigType("yaml")
err := v.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
v.WatchConfig()


v.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("config file changed:", e.Name)
if err = v.Unmarshal(&global.VUA_CONFIG); err != nil {
fmt.Println(err)
}
})
if err = v.Unmarshal(&global.VUA_CONFIG); err != nil {
fmt.Println(err)
}
return v
}

Expected Behavior

map is

config.yaml share_disk: - area: 4061 addr: 10.74.67.4

Actual Behavior

config.yaml share_disk: - area: 4061 addr: 10.74.67.4 - area: 4062 addr: 10.74.67.5

Steps To Reproduce

step: 1、config.yaml share_disk: - area: 4061 addr: 10.74.67.4 - area: 4062 addr: 10.74.67.5

2、The configuration read out is : share_disk: - area: 4061 addr: 10.74.67.4 - area: 4062 addr: 10.74.67.5

3、Then modify the configuration file to config.yaml share_disk: - area: 4061 addr: 10.74.67.4

4、The configuration read out is : Still the result of the second step

final result:The configuration has reduced one element but there is no hot update configuration

Additional Information

No response

Comment From: chengxilo

I tried it with the source code of main branch and this situation doesn't occur.(But the viper 1.19 which I downloaded with go mod did). Maybe it would be fixed in the next release.

Comment From: hutaochu

I encountered a similar problem: When I use viper.WatchConfig() to watch my config file and use viper.UnmarshalKey to get latest data from config file. When I remove a element from enable_list, the data obtained in viper is still the old version.

type Option struct {
    FullReleased bool     `mapstructure:"full_released"`
    EnableList   []string `mapstructure:"enable_list"`
    Domain       string   `mapstructure:"domain"`
}
var option Option
viper.OnConfigChange(func(e fsnotify.Event) {
    log.Logger().Info("Config file changed:" + e.Name)
    if err := viper.UnmarshalKey("option", &ption); err != nil {
        log.Logger().Error("load option failed")
        return
    }
    log.Logger().WithField("options", option).Info("option changed")
})
viper.WatchConfig()

this issue caused by mapstructure: https://github.com/mitchellh/mapstructure/blob/main/mapstructure.go#L1133 when you remove a element from a slice, the valSlice.Len() must grater than dataVal.Len(), so valSlice will not change.

https://github.com/mitchellh/mapstructure is read only, I'm not sure if this is a bug or a design issue, and whether it will be fixed in viper later.

Comment From: github-actions[bot]

Issues with no activity for 30 days are marked stale and subject to being closed.