emp

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 2, 2022 License: MIT Imports: 6 Imported by: 0

README

emp

Go Report Card Godoc Test Go Version

What is emp?

emp is a Go library for parsing environment variable to structures, while providing helpful error handling.

Why emp?

Directly read environment variables in Go will case a lot of repeat code like this:

package main

import "os"
    
func main() {
    envStringValue := os.Getenv("SOME_ENV")
	
    if envStringValue == "" {
        panic("missing SOME_ENV") 
        // OR: envStringValue = "default"
    }
    
    // convert string to the type you want
    envValue := sthConvert(envValue)
}    

It's a bit complicated and unclear, isn't it?

Let's try emp!

package main

import "github.com/XMLHexagram/emp"

func main() {
    type EnvModel struct {
        SOME_ENV   int
        SOME_ENV_1 string
        SOME_ENV_2 []string
        // whatever type you want, but not map
    }

    envModel := new(EnvModel)
    
    err := Parse(envModel)
    
    if err != nil {
        panic(err)
    }
}

Now, SOME_ENV is parsed to envModel.

It is simpler and easier to understand than the previous one, right?

What, no? Then you need to see Usage below.

Installation

Standard go get:

$ go get github.com/XMLHexagram/emp

Usage

For full usage and examples see the Godoc.

Or you can see Real Project Example, Test Case and Example Test Case

Here is a short introduction of emp:

Parse Environment variables to struct

The easiest way to use emp is to use Parse function.

First, define an empty struct:

type EnvModel struct {
    JWT_SECERT string
    JWT_EXPIRE int
    REDIS_URL  string
    SERVER_    struct {
        PORT         string
        HTTP_TIMEOUT int
    } 
    // whatever type you want, but not map
}

Then, Let's use emp.Marshal to see the environment variables emp will looking for.

res, err := emp.Marshal(&EnvModel{})

fmt.Println(res)
/*
JWT_SECERT=
JWT_EXPIRE=0
REDIS_URL=
// you want SERVER_PORT and SERVER_HTTP_TIMEOUT, right?
PORT=
HTTP_TIMEOUT=0
*/

Good, but not good enough. Maybe you want SERVER_PORT and SERVER_HTTP_TIMEOUT.

Let's try AutoPrefix:

parser, _ := emp.NewParser(&Config{
    AutoPrefix: true,
})

res, _ = parser.Marshal(&EnvModel{})

fmt.Println(res)
/*
JWT_SECERT=
JWT_EXPIRE=0
REDIS_URL=
// the prefix is `SERVER_` now!
SERVER_PORT=
SERVER_HTTP_TIMEOUT=0
*/

Much better, but can emp do something more?

Of course can, let's try field tag to customize the prefix and environment variable emp looking for:

type EnvModel struct {
    JwtSecret string `emp:"JWT_SECRET"`
    JwtExpire int    `emp:"JWT_EXPIRE"`
    RedisUrl  string `emp:"REDIS_URL"`
    Server    struct {
        Port        string `emp:"SERVER_PORT"`
        HttpTimeout int    `emp:"SERVER_HTTP_TIMEOUT"`
    } `emp:"prefix:SERVER_"`
    // whatever type you want, but not map
}

res, _ := emp.Marshal(&EnvModel1{})

fmt.Println(res)
/*
JWT_SECRET=
JWT_EXPIRE=0
REDIS_URL=
SERVER_SERVER_PORT=
SERVER_SERVER_HTTP_TIMEOUT=0
*/

COOL! This struct defines looks perfect. Now, we only need one more step.

Finally, call Parse function:

envModel := new(EnvModel)

_ := emp.Parse(envModel)

envModel is now filled with environment variables you need. 🎉

That's All?

No, emp also provides more features to customize your environment variables parsing.

See emp doc for more details.

Q & A

Why is it called "emp"?

A: emp => EnvironMent variable Parser

Does emp support case sensitive keys?

Yes, but maybe not in the future.

As we all know, environment variables in most time are ALL CAPS. So if someone need this feature, I will add it as a configurable option.

How to set environment variables?

There is an easy way to set environment variables by use godotenv

Support for map type?

No, the only not supported native type of Go is map. Sincerely, I have no idea on how to support it. If you have any idea, please open an issue.

Thanks

Thanks to mitchellh/mapstructure and [spf13/viper](https://github. com/spf13/viper), Your repos have inspired me, and I used some code from your repo.

More Feature or Bug Report

Feel free to open an issue when you want to report a bug, feature or ask for help. ✨

Documentation

Overview

Package emp exposes functionality to convert environment value into a struct.

The Go structure can be arbitrarily complex, containing slices, other structs, etc. and the parser will properly parse the environment value and populate the values into the native struct.

See the examples to see what the parser is capable of.

The simplest function to start with is Parser.

Field Tags

When decoding to a struct, emp will use the field name by default to perform the mapping. For example, if a struct has a field "DATABASE_URL" then emp will look for a key in the environment of "DATABASE_URL" (case-sensitive).

type Model struct {
    DATABASE_URL string
}

You can change the behavior of emp by using struct tags. The default struct tag that emp looks for is "emp" but you can customize it using Config.

Renaming Fields

To rename the key that emp looks for, use the "emp" tag and set a value directly. For example, to change the "DATABASE_URL" example above to "DATABASE_DSN":

type Model struct {
    DATABASE_URL string `emp:"DATABASE_DSN"`
}

Embedded Structs and Squashing

By default, Embedded structs are treated as prefix by their name. emp:

   type Model struct {
       DATABASE_URL string
       USER_ User
   }

   type User struct {
       Name string
		  Pass string
	  }

With environment value:

DATABASE_URL=postgres://user:pass@host:port/db
USER_NAME=user
USER_PASS=pass

Will be converted to:

type Model struct {
    DATABASE_URL: "postgres://user:pass@host:port/db",
    USER_: {
        Name: "user",
        Pass: "pass",
    },
}

Config has a field that changes the behavior of emp to disable auto prefix.

Unexported fields

Since unexported (private) struct fields cannot be set outside the package where they are defined, the parser will simply skip them.

For this output type definition:

type Exported struct {
    private string // this unexported field will be skipped
    PUBLIC string
}

Using this as environment value:

private=secret
PUBLIC=SECRET

The following struct will be parsed:

type Exported struct {
    private: "" // field is left with an empty string (zero value)
    Public: "SECRET"
}

Other Configuration

emp is highly configurable. See the Config struct for other features and options that are supported.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Marshal

func Marshal(inputPtrInterface interface{}) (string, error)

Marshal struct to get an env file format string.

func Parse

func Parse(inputPtrInterface interface{}) error

Parse takes an input structure and uses reflection to translate it to the output structure. output must be a pointer to a struct.

func ParseStringToArrayAndSlice

func ParseStringToArrayAndSlice(s string) []string

ParseStringToArrayAndSlice is the default parser for string to slice

Types

type Config

type Config struct {
	// ZeroFields, if set to true, will zero fields before writing them.
	// For example, a map will be emptied before parsed values are put in
	// it. If this is false, a map will be merged.
	ZeroFields bool

	// The TagName that emp reads for field names. This defaults to "emp".
	TagName string

	// Prefix, if set, will be the first part of all environment value name.
	Prefix string

	// AutoPrefix, default to true, it will add prefix automatically when meet embedded struct(use key).
	AutoPrefix bool

	// AllowEmpty, if set to true, will allow empty values in environment values.
	AllowEmpty bool

	// DirectDefault, if set to true, will use the default value in field name directly.
	DirectDefault bool

	// ParseStringToArrayAndSlice, customize the way split string to array and slice.
	ParseStringToArrayAndSlice func(s string) []string
	// contains filtered or unexported fields
}

Config is the configuration that is used to create a new parser and allows customization of various aspects of decoding.

type Parser

type Parser struct {
	// contains filtered or unexported fields
}

A Parser takes a raw interface value and fill it data, keeping track of rich error information along the way in case anything goes wrong. You can more finely control how the Parser behaves using the Config structure. The top-level parse method is just a convenience that sets up the most basic Parser.

func NewParser

func NewParser(config *Config) (*Parser, error)

NewParser returns a new parser for the given configuration. Once a parser has been returned, the same configuration must not be used again.

func (*Parser) Marshal

func (self *Parser) Marshal(StructPtrInterface interface{}) (string, error)

Marshal struct to get an env file format string.

func (*Parser) Parse

func (self *Parser) Parse(StructPtrInterface interface{}) error

Parse parses the given raw interface to the target pointer specified by the configuration.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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