Looking for feedback on Gonfig, a Go configuration library

Hi everyone,

I recently built a small Go library called Gonfig.

The idea came from repeatedly writing the same configuration code in almost every project. Reading environment variables, parsing CLI arguments, setting defaults, and validating required values is something I found myself doing over and over again.

So I decided to extract it into a reusable package.

With Gonfig, configuration can be defined directly on a struct:

var Config = gonfig.New[struct {
	Host   string `env:"APP_HOST" arg:"host" default:"localhost"`
	Port   int    `env:"APP_PORT" default:"8080"`
	Debug  bool   `arg:"debug" default:"false"`
	ApiKey string `env:"APP_API_KEY" arg:"apikey" required:""`
}](true)

Current features:

  • Load values from environment variables

  • Load values from command-line arguments

  • Default values

  • Required field validation

  • Nested struct support

  • Common Go types including time.Duration

I tried to keep it small and focused instead of turning it into a large framework.

This is an early release, so I’d appreciate any feedback from the Go community. I’m particularly interested in thoughts on the API design, tag structure, and whether there are any features you think would make it more useful.

Repository:
https://github.com/vrianta/golang/gonfig

Thanks for taking a look.

This is really similar to a library I wrote:

In your case, I think it’s slightly awkward to have a repo called golang and the import as a subfolder in that repo. I also think it’s more idiomatic to have required hang off the main tag rather than add an empty tag. Similar to json/omitempty:

Field int `json:"myName,omitempty"`
1 Like

Nice work! This is definitely a common pain point in Go projects.

It is also very similar to another library I wrote around 10 years ago: https://github.com/fulldump/goconfig

One design difference in goconfig is that it supports JSON config file(s) in addition to env vars, CLI flags, defaults, nested structs, slices and time.Duration, with deterministic precedence:

flags > env vars > JSON config file(s) > struct defaults

It also supports multiple config files, so a base config can be overridden by prod/local configs before env vars and flags are applied.

I agree with Dean’s point about the module path. A dedicated repository would probably feel more idiomatic than importing from a subfolder of a repo called golang. I’d also consider whether required should be part of the main tag, similar to json:",omitempty".

1 Like

I am trying to consolidate Packages of golang inside golang so that it would be vrianta/golang/tool1 or tool2. Because I am keeping other tools also in same repo. though I am thinking of repo referencing that directly having files here.

great project.

I am just trying to build a one in all struct perser, I used to call this code struct perser before the. realised the name is stupid and changed it to gonfig. but I got a good idea to add support for .env in my tool too.

Required is explicitly mentioned because I want to make it look like that the variable data is required instead particular type, because you also have arg mentioned with this tool. Not sure I thought this might be a good readable design.

Nice project got a good idea to add this config json thing.

But for micro services I think we should be prefering env variable before config and arg > env > config