1. 6
  1.  

  2. 4

    You can skip tons of the boilerplate here by using https://github.com/spf13/viper . I have used viper for my last few projects and it’s a huge timesaver. Supports TOML, as well as a bunch of other formats.

    1. 5

      I touched on this a bit in the reddit discussion, but I’ll expand here.

      I’ve checked out viper, but I personally don’t care for it for a couple reasons:

      • Its default behavior is to use a single global config, which makes testing more difficult and makes it really difficult to use pieces of an application as a library (I ran into this when trying to wrap Hugo - it uses a global viper, so it’s really hard to just use pieces of it). It has the ability to use an explicit state, but it’s not the default and not what I’ve typically seen in the wild. This approach makes the handling of config states explicit, which is my preferred style.
      • It’s stringly-typed by default, so if you don’t manually do something like what I suggest in this post (marshal into a struct in a single place) you can end up using reflection throughout your application, which has both type-safety and performance concerns. Yeah, my approach technically does use reflection, but it confines it to a library and does it all when reading the config. You can do the same with viper, but you have to do it manually (AFAIK).
      • This is more of a style concern, but viper seems to expect that your application will be built around using viper. This approach is much more contained, and you can use it however you want. It’s also much smaller and much simpler. I tend to prefer libraries that fit into my application, not ones that want my application to fit into them.
      • IMO, the boilerplate is a feature, not an issue. The vast majority of the boilerplate in this approach is just a declaration of what your config is actually supposed to look like - if you don’t do this, the shape of your config is implicit. If you do, even with another library, then you end up with pretty much the same amount of boilerplate.

      I haven’t explored viper a whole lot, so I’m sure there are other advantages. This approach has worked marvelously for me for several command-line applications, and I haven’t felt like I’m missing any necessary features.

      1. 2

        Thanks for your response! I agree with all your points, I’ve just found viper to be a good solution when I don’t want/don’t need to think about config too much but it’s clearly needed. I certainly still think everything you wrote is valuable and shouldn’t have implied otherwise.

    2. 1

      I built a tiny lib for working with json configs and go’s flag lib: https://github.com/zamicol/jsonflags