config

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Aug 21, 2023 License: MIT Imports: 10 Imported by: 1

README

ZH

config

Synopsis

// main.go
package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/Bofry/config"
)

func init() {
	// set env
	{
		// NOTE: you can run the following commands in bash
		// export ENVIRONMENT=production
		// export REDIS_HOST=127.0.0.3:6379
		// export REDIS_PASSWORD=1234
		// export K8S_REDIS_HOST=demo-kubernetes:6379
		// export K8S_REDIS_PASSWORD=p@ssw0rd
		// export K8S_REDIS_DB=6
		os.Clearenv()
		os.Setenv("ENVIRONMENT", "production")
		os.Setenv("REDIS_HOST", "127.0.0.3:6379")
		os.Setenv("REDIS_PASSWORD", "1234")
		os.Setenv("K8S_REDIS_HOST", "demo-kubernetes:6379")
		os.Setenv("K8S_REDIS_PASSWORD", "p@ssw0rd")
		os.Setenv("K8S_REDIS_DB", "6")
	}
	// generate .env
	{
		os.WriteFile(".env", []byte(
			strings.Join([]string{
				"REDIS_HOST=127.0.0.1:6379",
				"REDIS_DB=29",
				"TAG=demo,test",
			}, "\n")), 0644)
	}
	// generate .VERSION
	{
		os.WriteFile(".VERSION", []byte(
			strings.Join([]string{
				"v1.0.2",
			}, "\n")), 0644)
	}
	// generate config.yaml
	{
		os.WriteFile("config.yaml", []byte(
			strings.Join([]string{
				"redisDB: 3",
				"redisPoolSize: 10",
				"workspace: demo_test",
			}, "\n")), 0644)
	}
	// generate config.staging.yaml
	{
		os.WriteFile("config.staging.yaml", []byte(
			strings.Join([]string{
				"redisDB: 9",
				"redisPoolSize: 10",
				"workspace: demo_stag",
			}, "\n")), 0644)
	}
	// generate config.production.yaml
	{
		os.WriteFile("config.production.yaml", []byte(
			strings.Join([]string{
				"redisDB: 12",
				"redisPoolSize: 50",
				"workspace: demo_prod",
			}, "\n")), 0644)
	}
}

type DummyConfig struct {
	RedisHost     string   `env:"REDIS_HOST"       yaml:"redisHost"       arg:"redis-host;the Redis server address and port"`
	RedisPassword string   `env:"REDIS_PASSWORD"   yaml:"redisPassword"   arg:"redis-passowrd;the Redis password"`
	RedisDB       int      `env:"REDIS_DB"         yaml:"redisDB"         arg:"redis-db;the Redis database number"`
	RedisPoolSize int      `env:"-"                yaml:"redisPoolSize"`
	Workspace     string   `env:"-"                yaml:"workspace"       arg:"workspace;the data workspace"`
	Tags          []string `env:"TAG"`
	Version       string   `resource:".VERSION"`
}

func main() {
	conf := DummyConfig{}

	config.NewConfigurationService(&conf).
		LoadDotEnv().
		LoadEnvironmentVariables("").
		LoadEnvironmentVariables("K8S").
		LoadYamlFile("config.yaml").
		LoadYamlFile("config.${ENVIRONMENT}.yaml").
		LoadCommandArguments().
		LoadResource("")
	fmt.Printf("RedisHost     = %q\n", conf.RedisHost)
	fmt.Printf("RedisPassword = %q\n", conf.RedisPassword)
	fmt.Printf("RedisDB       = %d\n", conf.RedisDB)
	fmt.Printf("RedisPoolSize = %d\n", conf.RedisPoolSize)
	fmt.Printf("Workspace     = %q\n", conf.Workspace)
	fmt.Printf("Tags          = %q\n", conf.Tags)
	fmt.Printf("Version       = %q\n", conf.Version)
}

Open your terminal and execute the following command:

  • Bash
    $ go build -o example
    $ ./example -redis-db=32
    
  • Dos
    C:\> go build -o example.exe
    C:\> example.exe -redis-db=32
    

You will get:

RedisHost     = "demo-kubernetes:6379"
RedisPassword = "p@ssw0rd"
RedisDB       = 32
RedisPoolSize = 50
Workspace     = "demo_prod"
Tags          = ["demo" "test"]
Version       = "v1.0.2"

$~$

Struct Tag Denotation

configuration type struct tag tag flags ConfigurationService method example
environment variables env required LoadEnvironmentVariables() env:"CACHE_ADDRESS,required" -or- env:"*CACHE_ADDRESS"
.env files env required LoadDotEnv(), LoadDotEnvFile() env:"CACHE_ADDRESS,required" -or- env:"*CACHE_ADDRESS"
json files json -- LoadJsonFile() json:"LISTEN_PORT"
yaml files yaml -- LoadYamlFile() yaml:"LISTEN_PORT"
binary reource files resource required LoadResource() resource:"VERSION,required" -or- resource:"*VERSION"
text reource files resource required LoadResource() resource:"VERSION,required" -or- resource:"*VERSION"
command arguments arg -- LoadCommandArguments() arg:"SERVER_NAME" -or- arg:"SERVER_NAME;specify server name"

📝 The resource:"VERSION,required" is equivalent to resource:"*VERSION", but not equivalent to resource:"*VERSION,required". For examples:

tag name flag
resource:"VERSION,required" VERSION required
resource:"*VERSION" VERSION required
resource:"*VERSION,required" *VERSION required
resource:"*VERSION,required,_" *VERSION required
resource:"*VERSION,_" *VERSION none
resource:"VERSION,_" VERSION none

📝 If you want reserve the start "*" in name and keep the setting to optional, to append the blank flag "_" to tag.

📝 The nested struct on tag env, resource, and arg ARE NOT SUPPORTED. And field type can be defined as bool, int, uint, float, string, time.Duration, time.Time, url.URL, net.IP, []bool, []int, []uint, []float, []string, []time.Duration, []time.Time, []url.URL, []net.IP, bytes.Buffer, json.RawMessage, or github.com/Bofry/types.RawContent.

$~$

Environment Variables

⠿ The following Config structure will import environment variables CACHE_HOST, CACHE_PASSWORD, and CACHE_DB. The tag text env:"CACHE_HOST,required" use the flag required indicates the environment variable CACHE_HOST is required. It will get exception if the variable doesn't be assgined.

type Config struct {
  CacheHost     string `env:"CACHE_HOST,required"`
  CachePassword string `env:"CACHE_PASSWORD"`
  CacheDB       int    `env:"CACHE_DB"`
}

The tag form env:"CACHE_HOST,required" also can be written as env:"*CACHE_HOST". Put the symbol "*" in front of the name is equivalent to appending required to tag flag part.

type Config struct {
  CacheHost     string `env:"*CACHE_HOST"`
  CachePassword string `env:"CACHE_PASSWORD"`
  CacheDB       int    `env:"CACHE_DB"`
}

$~$

.env Files

⠿ The .env files same as Environment Variables.

📝 The .env file WILL NOT OVERRIDE an environment variable that already exists. To consider .env file to set dev variable or sensible defaults.

$~$

Resource Files

⠿ The following Config structure will import content from file VERSION. The tag text resource:"VERSION,required" use the flag required indicates the file VERSION is required. It will get exception if the file doesn't exist.

type Config struct {
  AppVersion string `resource:"VERSION,required"`
}

The tag form resource:"VERSION,required" also can be written as resource:"*VERSION". Put the symbol "*" in front of the name is equivalent to appending required to tag flag part.

type Config struct {
  AppVersion string `resource:"*VERSION"`
}

📝 The name can compose by any unicode but no space character at the start or end, and no period at the end.

$~$

Command Arguments

⠿ The following Config structure will import command arguments cache-host, cache-passowrd, and cache-db. The tag text arg:"cache-host;the cache server address and port" separated by symbol ";" to two parts. The name part and the usage text part for help.

type Config struct {
	CacheHost     string `arg:"cache-host;the cache server address and port"`
	CachePassword string `arg:"cache-passowrd;the cache server password"`
	CacheDB       int    `arg:"cache-db;the cache database number"`
}

⛔ Don't name arg as help.

$~$

Dependency

Documentation

Overview

Example
package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/Bofry/config"
)

func main() {
	// set env
	{
		os.Clearenv()
		os.Setenv("ENVIRONMENT", "production")
		os.Setenv("REDIS_HOST", "127.0.0.3:6379")
		os.Setenv("REDIS_PASSWORD", "1234")
		os.Setenv("K8S_REDIS_HOST", "demo-kubernetes:6379")
		os.Setenv("K8S_REDIS_PASSWORD", "p@ssw0rd")
		os.Setenv("K8S_REDIS_DB", "6")
	}
	// set command line arguments
	{
		os.Args = []string{"example", "-redis-db", "32"}
		flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
	}
	// generate .env
	{
		os.WriteFile(".env", []byte(
			strings.Join([]string{
				"REDIS_HOST=127.0.0.1:6379",
				"REDIS_DB=29",
				"TAG=demo,test",
			}, "\n")), 0644)
	}
	// generate .VERSION
	{
		os.WriteFile(".VERSION", []byte(
			strings.Join([]string{
				"v1.0.2",
			}, "\n")), 0644)
	}
	// generate config.yaml
	{
		os.WriteFile("config.yaml", []byte(
			strings.Join([]string{
				"redisDB: 3",
				"redisPoolSize: 10",
				"workspace: demo_test",
			}, "\n")), 0644)
	}
	// generate config.staging.yaml
	{
		os.WriteFile("config.staging.yaml", []byte(
			strings.Join([]string{
				"redisDB: 9",
				"redisPoolSize: 10",
				"workspace: demo_stag",
			}, "\n")), 0644)
	}
	// generate config.production.yaml
	{
		os.WriteFile("config.production.yaml", []byte(
			strings.Join([]string{
				"redisDB: 12",
				"redisPoolSize: 50",
				"workspace: demo_prod",
			}, "\n")), 0644)
	}

	conf := struct {
		RedisHost     string   `env:"REDIS_HOST"       yaml:"redisHost"       arg:"redis-host;the Redis server address and port"`
		RedisPassword string   `env:"REDIS_PASSWORD"   yaml:"redisPassword"   arg:"redis-passowrd;the Redis password"`
		RedisDB       int      `env:"REDIS_DB"         yaml:"redisDB"         arg:"redis-db;the Redis database number"`
		RedisPoolSize int      `env:"-"                yaml:"redisPoolSize"`
		Workspace     string   `env:"-"                yaml:"workspace"       arg:"workspace;the data workspace"`
		Tags          []string `env:"TAG"`
		Version       string   `resource:".VERSION"`
	}{}

	config.NewConfigurationService(&conf).
		LoadDotEnv().
		LoadEnvironmentVariables("").
		LoadEnvironmentVariables("K8S").
		LoadYamlFile("config.yaml").
		LoadYamlFile("config.${ENVIRONMENT}.yaml").
		LoadCommandArguments().
		LoadResource("")
	fmt.Printf("RedisHost     = %q\n", conf.RedisHost)
	fmt.Printf("RedisPassword = %q\n", conf.RedisPassword)
	fmt.Printf("RedisDB       = %d\n", conf.RedisDB)
	fmt.Printf("RedisPoolSize = %d\n", conf.RedisPoolSize)
	fmt.Printf("Workspace     = %q\n", conf.Workspace)
	fmt.Printf("Tags          = %q\n", conf.Tags)
	fmt.Printf("Version       = %q\n", conf.Version)
}
Output:

RedisHost     = "demo-kubernetes:6379"
RedisPassword = "p@ssw0rd"
RedisDB       = 32
RedisPoolSize = 50
Workspace     = "demo_prod"
Tags          = ["demo" "test"]
Version       = "v1.0.2"

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ArbitraryPrinter added in v0.2.1

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

func NewArbitraryPrinter added in v0.2.1

func NewArbitraryPrinter(writer io.Writer, successor Printer) *ArbitraryPrinter

func (*ArbitraryPrinter) Print added in v0.2.1

func (p *ArbitraryPrinter) Print(target interface{}) error

type CommonPrinter added in v0.2.1

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

func NewCommonPrinter added in v0.2.1

func NewCommonPrinter(writer io.Writer) *CommonPrinter

func (*CommonPrinter) Print added in v0.2.1

func (p *CommonPrinter) Print(v interface{}) error

type ConfigurationService

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

func NewConfigurationService

func NewConfigurationService(target interface{}) *ConfigurationService

func (*ConfigurationService) LoadBytes

func (service *ConfigurationService) LoadBytes(buffer []byte, unmarshal UnmarshalFunc) *ConfigurationService

func (*ConfigurationService) LoadCommandArguments

func (service *ConfigurationService) LoadCommandArguments() *ConfigurationService

func (*ConfigurationService) LoadDotEnv

func (service *ConfigurationService) LoadDotEnv() *ConfigurationService

func (*ConfigurationService) LoadDotEnvFile

func (service *ConfigurationService) LoadDotEnvFile(filepath string) *ConfigurationService

func (*ConfigurationService) LoadEnvironmentVariables

func (service *ConfigurationService) LoadEnvironmentVariables(prefix string) *ConfigurationService

func (*ConfigurationService) LoadFile

func (service *ConfigurationService) LoadFile(fullpath string, unmarshal UnmarshalFunc) *ConfigurationService
Example
// prepare config.yaml
{
	os.WriteFile("config.yaml", []byte(
		strings.Join([]string{
			"redisDB: 3",
			"redisPoolSize: 10",
			"workspace: demo_test",
		}, "\n")), 0644)
}

conf := struct {
	RedisHost     string   `env:"REDIS_HOST"       yaml:"redisHost"       arg:"redis-host;the Redis server address and port"`
	RedisPassword string   `env:"REDIS_PASSWORD"   yaml:"redisPassword"   arg:"redis-passowrd;the Redis password"`
	RedisDB       int      `env:"REDIS_DB"         yaml:"redisDB"         arg:"redis-db;the Redis database number"`
	RedisPoolSize int      `env:"-"                yaml:"redisPoolSize"`
	Workspace     string   `env:"-"                yaml:"workspace"       arg:"workspace;the data workspace"`
	Tags          []string `env:"TAG"`
	Version       string   `resource:".VERSION"`
}{}

config.NewConfigurationService(&conf).
	LoadFile("config.yaml", yaml.Unmarshal)
fmt.Printf("RedisHost     = %q\n", conf.RedisHost)
fmt.Printf("RedisPassword = %q\n", conf.RedisPassword)
fmt.Printf("RedisDB       = %d\n", conf.RedisDB)
fmt.Printf("RedisPoolSize = %d\n", conf.RedisPoolSize)
fmt.Printf("Workspace     = %q\n", conf.Workspace)
fmt.Printf("Tags          = %q\n", conf.Tags)
fmt.Printf("Version       = %q\n", conf.Version)
Output:

RedisHost     = ""
RedisPassword = ""
RedisDB       = 3
RedisPoolSize = 10
Workspace     = "demo_test"
Tags          = []
Version       = ""

func (*ConfigurationService) LoadJsonBytes

func (service *ConfigurationService) LoadJsonBytes(buffer []byte) *ConfigurationService

func (*ConfigurationService) LoadJsonFile

func (service *ConfigurationService) LoadJsonFile(filepath string) *ConfigurationService

func (*ConfigurationService) LoadResource

func (service *ConfigurationService) LoadResource(baseDir string) *ConfigurationService

func (*ConfigurationService) LoadYamlBytes

func (service *ConfigurationService) LoadYamlBytes(buffer []byte) *ConfigurationService

func (*ConfigurationService) LoadYamlFile

func (service *ConfigurationService) LoadYamlFile(filepath string) *ConfigurationService

func (*ConfigurationService) Map added in v0.2.1

func (service *ConfigurationService) Map(mapper structproto.StructMapper) error

func (*ConfigurationService) Output added in v0.2.1

func (service *ConfigurationService) Output()

func (*ConfigurationService) OutputWithPrinter added in v0.2.1

func (service *ConfigurationService) OutputWithPrinter(printer Printer)

type NonePrinter added in v0.2.1

type NonePrinter struct{}

func (NonePrinter) Print added in v0.2.1

func (NonePrinter) Print(target interface{}) error

type Printable added in v0.2.1

type Printable interface {
	Output(writer io.Writer) error
}

type Printer added in v0.2.1

type Printer interface {
	Print(target interface{}) error
}

type UnmarshalFunc

type UnmarshalFunc func(buffer []byte, target interface{}) error

Directories

Path Synopsis
internal
env

Jump to

Keyboard shortcuts

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