Help us shape the future of Go! Take the 2026 Go Developer Survey

config

package module
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Sep 29, 2024 License: MIT Imports: 10 Imported by: 3

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) ExpandEnv added in v0.2.2

func (service *ConfigurationService) ExpandEnv(prefix string) error

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
package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/Bofry/config"
	"gopkg.in/yaml.v2"
)

func main() {
	// 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