2

I am using viper for my config. How do I replace a key without replacing the entire map?

package main

import (
    "log"

    "github.com/spf13/viper"
)

type person struct {
    First string
    Last  string
}

func main() {
    v := viper.New()
    v.SetEnvPrefix("mememe")
    v.AutomaticEnv()

    bob := person{
        First: "Bob",
        Last:  "Smith",
    }

    john := person{
        First: "John",
        Last:  "Boothe",
    }

    v.SetDefault("people.bob", bob)
    v.SetDefault("people.john", john)
    log.Println(v.Get("people")) // map[bob:{Bob Smith} john:{John Boothe}]

    bob.Last = "Hope"
    v.Set("people.bob", bob)
    log.Println(v.Get("people")) // map[bob:{Bob Hope}]

}

Upon setting the new Bob I lose John completely. If I change "SetDefault" to simply "Set" then it seems to work but I am wondering why "SetDefault" doesn't work.

1 Answers1

0

I'm going to guess it's because of this, from the docs on Accessing nested keys.

However, if datastore.metric was overridden (by a flag, an environment variable, the Set() method, …) with an immediate value, then all sub-keys of datastore.metric become undefined, they are “shadowed” by the higher-priority configuration level.

So as soon as people.bob is set, people springs into existence and people.* are no longer considered unpopulated.

I don't know how to work around it.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • 1
    I guess that makes sense but then again it doesn't. –  May 29 '17 at 18:04
  • @kristen Might be worth reporting as a bug/misfeature. Smells like a quirk of the implementation rather than a feature. – Schwern May 29 '17 at 18:10