env

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 11, 2022 License: BSD-3-Clause Imports: 6 Imported by: 1

README

STRV env

Go package for runtime environment configuration.

env package leverage Go's reflection functionality for scanning structures. If the env tag is found, a value of this tag is used for env lookup. If the env variable is set, the value in the structure is overridden. There are two ways how to process structures:

  • If a tag value contains ,dive, inner fields of a structure are processed (Session in the example).
  • If a structure implements the encoding.TextUnmarshaler interface, UnmarshalText is called for the given structure (AccessTokenExpiration or zap.AtomicLevel in the example).

A good practice when overriding a config with env variables is to use an app prefix. If the env variable APP_PREFIX contains some value (MY_APP for example), each defined env variable has to contain the prefix MY_APP (MY_APP_PORT in the example). There is also an option to choose a custom prefix for env variables by calling MustApplyWithPrefix.

It may happen that the app needs to consume an env variable set by a third party. It's no exception that a cloud provider sets a port your app needs to listen on and you are unable to modify it. In this case, there is an option to enhance the env tag with the ignoreprefix clause (env:"PORT,ignoreprefix"). While other env variables will be searched with a prefix included, PORT not.

Examples

package main

import (
	envx "go.strv.io/env"
	timex "go.strv.io/time"

	"go.uber.org/zap"
)

type config struct {
	Port        uint   `json:"port" env:"PORT"`
	StorageAddr string `json:"storage_addr" env:"STORAGE_ADDR"`
	Session     struct {
		AccessTokenExpiration timex.Duration `json:"access_token_expiration" env:"SESSION_ACCESS_TOKEN_EXPIRATION"`
	} `json:"session" env:",dive"`
	LogLevel zap.AtomicLevel `json:"log_level" env:"LOG_LEVEL"`
}

func main() {
	cfg := config{}
	envx.MustApply(&cfg)
}

See detailed example.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Apply

func Apply(target any) error

Apply applies the environment variables to the given target.

Example
package main

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"time"

	envx "go.strv.io/env"
)

type debug bool

func (d *debug) UnmarshalText(text []byte) error {
	if d == nil {
		return fmt.Errorf("debug: UnmarshalText: nil pointer")
	}

	b, err := strconv.ParseBool(string(text))
	if err != nil {
		return err

	}
	*d = debug(b)
	return nil
}

type serviceConfig struct {
	Addr    string        `env:"ADDR"`
	Debug   *debug        `env:"DEBUG"`
	Metrics metricsConfig `env:",dive"`
}

type metricsConfig struct {
	Namespace string `env:"METRICS_NAMESPACE"`
}

func main() {
	cfg := serviceConfig{}
	err := os.Setenv("APP_PREFIX", "EXAMPLE")
	if err != nil {
		panic(err)
	}

	err = os.Setenv("EXAMPLE_ADDR", ":8080")
	if err != nil {
		panic(err)
	}

	envx.MustApply(&cfg)

	//nolint:gosec
	server := &http.Server{Addr: cfg.Addr}
	fmt.Println("Starting HTTP server on address: ", cfg.Addr)

	go func() {
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			panic(err)
		}
	}()

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := server.Shutdown(ctx); err != nil {
		panic(err)
	}

}
Output:

Starting HTTP server on address:  :8080

func ApplyWithPrefix

func ApplyWithPrefix(target any, prefix string) error

ApplyWithPrefix applies the environment variables to the given target.

The prefix is used to prefix the environment variables specified by the `env` tag.

func MustApply

func MustApply(target any)

MustApply calls Apply and panics on error.

func MustApplyWithPrefix

func MustApplyWithPrefix(target any, prefix string)

MustApplyWithPrefix calls ApplyWithPrefix and panics on error.

Types

type InvalidTypeError

type InvalidTypeError struct {
	Type reflect.Value
}

InvalidTypeError is returned when the type of the target is not a valid type.

func (*InvalidTypeError) Error

func (e *InvalidTypeError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL