Skip to content

Latest commit

 

History

History
274 lines (199 loc) · 4.4 KB

README.md

File metadata and controls

274 lines (199 loc) · 4.4 KB

env: Parse environment variables, map to structs

Go Go Report Card Coverage Status

env is a mapper from environment variables to structs

Features

  • Ability to map environment variables to structs
  • Ability to customize environment variables with struct tags
  • Ability to parse nested/sub structs
  • Ability to parse embedded nested/sub structs
  • Ability to parse and map types (bool, string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, complex64, complex128, struct)

Getting started

Install

// Requires go1.15+

go get github.com/aacanakin/env

Usage

// main.go
package main

import "fmt"
import "github.com/aacanakin/env"

type Config struct {
  Host string
  Port int
  Debug bool
}

func main() {

  var c Config

  err := env.Parse(&c)
  if err != nil {
    panic(err)
  }

  fmt.Println("Host: ", c.Host)
  fmt.Println("Port: ", c.Port)
  fmt.Println("Debug: ", c.Debug)
}

Run

$ HOST=localhost PORT=8081 debug=true go run main.go

// Output
Host:  localhost
Port:  8081
Debug:  true

Custom environment var mapping

// main.go
package main

import "fmt"
import "github.com/aacanakin/env"

func main() {
  type Config struct {
    Host string `env:"SERVICE_HOST"`
    Port int    `env:"SERVICE_PORT"`
    Debug bool  `env:"SERVICE_DEBUG"`
  }

  var c Config

  err := env.Parse(&c)
  if err != nil {
    panic(err)
  }

  fmt.Println("Host: ", c.Host)
  fmt.Println("Port: ", c.Port)
  fmt.Println("Debug: ", c.Debug)
}

Run

SERVICE_HOST=localhost SERVICE_PORT=8081 SERVICE_DEBUG=true go run main.go

// Output
Host:  localhost
Port:  8081
Debug:  true

Nested/Sub structs

// main.go
package main

import "fmt"
import "github.com/aacanakin/env"

type db struct {
  Host string `env:"DB_HOST"`
  Port int `env:"DB_PORT"`
}

type service struct {
  Debug bool `env:"SERVICE_DEBUG"`
}

type Config struct {
  DB db
  Service service
}

func main() {
  var c Config

  err := env.Parse(&c)
  if err != nil {
    panic(err)
  }

  fmt.Println("DB Host: ", c.DB.Host)
  fmt.Println("DB Port: ", c.DB.Port)
  fmt.Println("Service Debug: ", c.Service.Debug)
}

Run

DB_HOST=localhost DB_PORT=3306 SERVICE_DEBUG=true go run main.go

// Output
DB Host:  localhost
DB Port:  3306
Service Debug:  true

Using with .env

Install

go get github.com/joho/godotenv

Create a .env file

# .env
HOST=localhost
PORT=8081
// main.go
package main

import (
  "github.com/joho/godotenv"
  "github.com/aacanakin/env"
  "log"
)

type Config struct {
  Host string
  Port uint16
}

func main() {
  err := godotenv.Load()
  if err != nil {
    log.Fatal("Error loading .env file")
  }

  var c Config

  err = env.Parse(&c)

  log.Println("Host: ", c.Host)
  log.Println("Port: ", c.Port)
}

Readonly config

Since it's a good practice to keep environment variables immutable, it will be also a good practice to keep the parsed struct immutable too. However, Go's reflect package doesn't allow setting unexported fields. So, to keep the struct immutable;

  • Create a config package
package config

import "github.com/aacanakin/env"

type conf struct {
	Host string
	Port uint16
}

type Config struct {
	conf conf
}

func (c Config) Host() string {
	return c.conf.Host
}

func (c Config) Port() uint16 {
	return c.conf.Port
}

func New() (*Config, error) {
	var c conf
	err := env.Parse(&c)
	if err != nil {
		return nil, err
	}

	return &Config{c}, nil
}
  • Use it in your main.go
package main

import (
	"fmt"

	"github.com/aacanakin/env_test/config"
)

func main() {
  c, err := config.New()
  if err != nil {
    panic(err)
  }

  // HERE, c.conf is not accessible
  fmt.Println("Host:", c.Host())
  fmt.Println("Port:", c.Port())
}

NOTE: This looks like it's not very idiomatic go. Feedbacks here are welcome.

Roadmap

  • omitempty tag constraint
  • file tag constraint
  • Ability to customize tag key (default is env)
  • Provide an instance based parser
  • Provide a read only config example with custom conf package
  • Release v0.1