I don't want to "beat around the bush", so I'll just familiarize you with the functionality of my library and try to explain why it's convenient and why you should try it.
What's inside
Define the configuration contract using Golang Structures and Tags:
Variable name
Default value
Permission not to set the variable value
Description for documentation.
Unmarshal from Environment Variables, .env files, or implement, for example your own Custom Value Provider for YAML and inject it.
Custom Value Parsers
Not satisfied with the default Value Parsers? Want the value 10 to be parsed into the number 83 during unmarshalling? Or maybe you want to parse your own type, like time.Duration? It's covered by gocfg!
Automatic Documentation Generation based on the contract.
Quick view
Start by importing go get -u github.com/Jagerente/gocfg.
Create an internal configuration package, for example - internal/config/config.go.
I believe that the tag names are informative and intuitive enough, but just in case, let's go through them:
env - Specifies the variable name in the configuration file and is necessary for Value Provider implementations to map Key-Value.
default - Specifies the default value of the variable.
omitempty - Means that the variable can be left undeclared, and then the default value will be used, or if the default is missing, the field will take Golang's zero value; for example, 0 for int type or false for bool type.
description - The field is used during automatic documentation generation. It is necessary to provide a description of the variable.
title - The field is used during automatic documentation generation. It is necessary to separate groups of variables; a group consists of variables in a separate structure, for example, LoggerConfig is a separate group of variables.
Let's go back to the functionality and inspect it:
values.NewEnvProvider() - Parser for Environment Variables.
Not to be confused with .env file!
.ENV files parser
Let's add parsing values from the .env file, the driver is available out of the box:
funcNew()(*Config,error){// With default '.env' filedotEnvProvider,_:=values.NewDotEnvProvider()// With custom env file path dotEnvProvider,_=values.NewDotEnvProvider("local.env")// With multiple env filesdotEnvProvider,_=values.NewDotEnvProvider("local.env","dev.env")varcfg=new(Config)cfgManager:=gocfg.NewEmpty().UseDefaults().AddParserProviders(parsers.NewDefaultParserProvider()).AddValueProviders(values.NewEnvProvider(),dotEnvProvider,)iferr:=cfgManager.Unmarshal(cfg);err!=nil{returnnil,err}returncfg,nil}
You might be wondering:
What will happen when using multiple .env files?
Values will be read and written in the order from the first added to the last added file. Suppose the first file has 5/10 variables, and the second has 7/10, then the second file will overwrite 2 intersecting values that were already written from the first file, and the missing ones will simply be written.
Or:
What about the priority of value providers, when you add multiple?
When attempting to retrieve a value from all value providers in the order from the first added to the last added, the first non-empty value will be returned.
Different Key Tag name
All you need is add .UseCustomKeyTag("mapstructure"):
Run it with go run cmd/docs/main.go; after which the file .env.dist.generated will be generated:
# Auto-generated config
#############################
# Logger configuration
#############################
# Description:
# Possible values:
# 0 - Trace
# 1 - Debug
# 2 - Info
# 3 - Error
LOG_LEVEL=6
REPORT_CALLER=true
LOG_FORMATTER=0
#############################
# Router configuration
#############################
SERVER_PORT=8080
ROUTER_DEBUG=true
# Allowed to be empty
# Description:
# Leave blank to not use.
# Possible values:
# - redis
# - memcache
CACHE_ADAPTER=
# Allowed to be empty
CACHE_ADAPTER_TTL=1m
# Allowed to be empty
CACHE_ADAPTER_NOCACHE_PARAM=no-cache
#############################
# Cassandra configuration
#############################
CASSANDRA_HOSTS=127.0.0.1
CASSANDRA_KEYSPACE=messenger
This is my very first open-source library, as well as this article, so If you've reached this point, I'm truly grateful to you. I'd like to ask you to share the most important thing - criticism! I also won't refuse kind words, stars on GitHub repository and any kind of support in promoting this library. <3
This project is open to contributions. If you wish to add your own implementation of a Value Provider driver or Documentation Generator, or perhaps you'd like to conduct a code review or suggest improvements, feel free to submit a pull request or contact me!