startup

package module
v1.0.9 Latest Latest
Warning

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

Go to latest
Published: Feb 13, 2024 License: MIT Imports: 11 Imported by: 0

README

godoc Go Report Card go test Go Coverage

Package startup

Use the package's functionality to simplify the use of flags, environments and config file when starting the application.
Fill custom Golang struct from environments, flags or configuration file (JSON) with desired order.
Convenient for setting up an application for a container (Docker, Podman)

Install
go get github.com/KusoKaihatsuSha/startup
Update
go get -u
go mod tidy
Usage

img_3.png

type CustomConf struct {
    VarStr string `json:"t-str" default:"abcd" flag:"t-str" env:"T_STR" help:"description"`
}

Order (low -> high) [FILE -> ENV -> FLAG]:

filledCustomConf := startup.Get[CustomConf](
	startup.FILE,
	startup.ENV,
	startup.FLAG,
	)
Example 01
// Some struct
type Configuration struct {
    TestString   string        `json:"test-string"   default:"abcd"          flag:"test-string"   env:"TEST_STR"      help:"string"`
    TestInt      int64         `json:"test-int"      default:"11"            flag:"test-int"      env:"TEST_INT"      help:"int"`
    TestDuration time.Duration `json:"test-duration" default:"1s"            flag:"test-duration" env:"TEST_DURATION" help:"duration"`
    TestBool     bool          `json:"test-bool"     default:"false"         flag:"test-bool"     env:"TEST_BOOL"     help:"bool"`
    TestFloat    float64       `json:"test-float"    default:"1"             flag:"test-float"    env:"TEST_FLOAT"    help:"float"`
    TestUint     uint64        `json:"test-uint"     default:"111"           flag:"test-uint"     env:"TEST_UINT"     help:"uint"`
}

func main() {
    // Emulated settings at startup
    os.Setenv("TEST_STR", "dcba")
    os.Setenv("TEST_UINT", "999")
    os.Setenv("TEST_DURATION", "11h")
    os.Args = append(
        os.Args,
        "-test-bool",
        "-test-uint=741",
    )
    
    // Get filled configs (ORDER: Environment -> Flags ).
    config := startup.GetForce[Configuration](
        startup.ENV,
        startup.FLAG,
    )
    
    // Print result => {dcba 11 11h0m0s true 1 741}
    fmt.Printf("%v\n", config)
}
Example 02
package main

import (
    "encoding/json"
    "fmt"
    "net"
    "strings"
    "time"
    
    "github.com/KusoKaihatsuSha/startup"
)

// Custom struct
type Configuration struct {
    TestEmail    string        `json:"test-email"    default:"a@b.c"         flag:"test-email"    env:"TEST_EMAIL"    help:"email"`
    TestSlice    []string      `json:"test-slice"    default:"1,2,3,4;5;6"   flag:"test-slice"    env:"TEST_SLICE"    help:"slice" valid:"slice"`
    TestInt      int64         `json:"test-int"      default:"11"            flag:"test-int"      env:"TEST_INT"      help:"int"`
    TestDuration time.Duration `json:"test-duration" default:"1s"            flag:"test-duration" env:"TEST_DURATION" help:"duration"`
    TestBool     bool          `json:"test-bool"     default:"true"          flag:"test-bool"     env:"TEST_BOOL"     help:"bool"`
    TestFloat    float64       `json:"test-float"    default:"1"             flag:"test-float"    env:"TEST_FLOAT"    help:"float"`
    TestUint     uint64        `json:"test-uint"     default:"111"           flag:"test-uint"     env:"TEST_UINT"     help:"uint"`
    TestIP       net.IP        `json:"test-ip"       default:"127.0.0.1"     flag:"test-ip"       env:"TEST_IP"       help:"ip"`
    TestJSON     TestJSON      `json:"test-json"     default:"{\"param1\":\"default_001\",\"param2\":\"default_002\"}" flag:"test-json" env:"TEST_JSON" help:"json"`
}

// JSON field and unmashalText
type TestJSON struct {
    P1 string `json:"param1"`
    P2 string `json:"param2"`
}

func (t *TestJSON) UnmarshalText(text []byte) error {
    type Tmp TestJSON
    tmp := (*Tmp)(t)
    if err := json.Unmarshal(text, tmp); err != nil {
        return err
    }
    t = (*TestJSON)(tmp)
    return nil
}

// Custom slice validation  
type sliceValid string

var sliceValidation sliceValid = "slice"

func (o sliceValid) Valid(def string, value any) (any, bool) {
    newValue := strings.ReplaceAll(def, ";", ",")
    return strings.Split(newValue, ","), true
}

func main() {
    
    // Add custom validation
    startup.AddValidation(sliceValidation)
	
    // Implement all types of configs (ORDER: Json file -> Environment -> Flags ).
    get := startup.Get[Configuration](
        startup.FILE,
        startup.ENV,
        startup.FLAG,
    )
    
    fmt.Printf(
        "string ↣ TYPE [%[1]T] VALUE [%[1]v]\n",
        get.TestEmail,
    )
    
    fmt.Printf(
        "custom slice ↣ TYPE [%[1]T] VALUE [%[1]v]\n",
        get.TestSlice,
    )
    
    fmt.Printf(
        "integer max 10 ↣ TYPE [%[1]T] VALUE [%[1]v]\n",
        get.TestInt,
    )
    
    fmt.Printf(
        "duration ↣ TYPE [%[1]T] VALUE [%[1]v]\n",
        get.TestDuration,
    )
    
    fmt.Printf(
        "boolean ↣ TYPE [%[1]T] VALUE [%[1]v]\n",
        get.TestBool,
    )
    
    fmt.Printf(
        "float ↣ TYPE [%[1]T] VALUE [%[1]v]\n",
        get.TestFloat,
    )
    
    fmt.Printf(
        "uint ↣ TYPE [%[1]T] VALUE [%[1]v]\n",
        get.TestUint,
    )
    
    fmt.Printf(
        "ip ↣ TYPE [%[1]T] VALUE [%[1]v]\n",
        get.TestIP,
    )
    
    fmt.Printf(
        "json unmarshal ↣ TYPE [%[1]T] VALUE [%#[1]v]\n",
        get.TestJSON,
    )
}
Default validations (in tag valid inside annotation)
  • tmp_file - Check exist inside Temp folder and create if not exist (string in struct)
  • file - Check exist the filepath and create if not exist (string in struct)
  • url - Check url is correct (string in struct)
  • bool - Parse Bool (bool in struct)
  • int - Parse int (int64 in struct)
  • float - Parse float (float64 in struct)
  • duration - Parse duration (time.Duration in struct)
  • uuid - Check uuid. Return new if not exist (string in struct)
Caution

Default config filename:

  • config.ini

Flags are reserved:

  • config

Environments are reserved:

  • CONFIG
Print -h or -help tag Example
Order of priority for settings (low -> high):
Config file (JSON) --> Environment --> Flags

  -config
        Configuration settings file
        Default value: config.ini
        Sample JSON config:
        {
          "startup_configuration_file": "config.ini"
        }
        Sample environment:     CONFIG=config.ini
        Sample flag value:      testee.exe -config=config.ini

  -test-bool
        bool
        Default value: true
        Sample JSON config:
        {
          "test-bool": true
        }
        Sample environment:     TEST_BOOL=true
        Sample(TRUE):     testee.exe -test-bool
        Sample(default):  testee.exe
        Sample(TRUE):   testee.exe -test-bool=true
        Sample(FALSE):  testee.exe -test-bool=false
        Sample(TRUE):   testee.exe -test-bool=1
        Sample(FALSE):  testee.exe -test-bool=0
        Sample(TRUE):   testee.exe -test-bool=t
        Sample(FALSE):  testee.exe -test-bool=f

  -test-duration
        duration
        Default value: 1s
        Sample JSON config:
        {
          "test-duration": 1000000000
        }
        Sample environment:     TEST_DURATION=1s
        Sample(Millisecond):    testee.exe -test-duration=1ms
        Sample(Second): testee.exe -test-duration=1s
        Sample(Minute): testee.exe -test-duration=1m
        Sample(Hour):   testee.exe -test-duration=1h
        Sample(Nanosecond):     testee.exe -test-duration=1ns
        Sample(Microsecond):    testee.exe -test-duration=1us
        Sample(1 Hour 2 Minutes and 3 Seconds): testee.exe -test-duration=1h2m3s
        Sample(111 Seconds):    testee.exe -test-duration=111

  -test-email
        email
        Default value: a@b.c
        Sample JSON config:
        {
          "test-email": "a@b.c"
        }
        Sample environment:     TEST_EMAIL=a@b.c
        Sample flag value:      testee.exe -test-email=a@b.c

  -test-float
        float
        Default value: 1
        Sample JSON config:
        {
          "test-float": 1
        }
        Sample environment:     TEST_FLOAT=1
        Sample flag value:      testee.exe -test-float=1.000000

  -test-int
        int
        Default value: 11
        Sample JSON config:
        {
          "test-int": 11
        }
        Sample environment:     TEST_INT=11
        Sample flag value:      testee.exe -test-int=11

  -test-ip
        ip
        Default value: 127.0.0.1
        Sample JSON config:
        {
          "test-ip": "127.0.0.1"
        }
        Sample environment:     TEST_IP=127.0.0.1

  -test-json
        json
        Default value: {default_001 default_002}
        Sample JSON config:
        {
          "test-json": {
            "param1": "default_001",
            "param2": "default_002"
          }
        }
        Sample environment:     TEST_JSON={"param1":"default_001","param2":"default_002"}

  -test-slice
        slice
        Default value: []
        Sample JSON config:
        {
          "test-slice": null
        }
        Sample environment:     TEST_SLICE=1,2,3,4;5;6

  -test-uint
        uint
        Default value: 111
        Sample JSON config:
        {
          "test-uint": 111
        }
        Sample environment:     TEST_UINT=111
        Sample flag value:      testee.exe -test-uint=111

Documentation

Overview

Example (ConfigOrderConfFlagEnv)
package main

import (
	"encoding/json"
	"fmt"
	"net"
	"os"
	"time"

	"github.com/KusoKaihatsuSha/startup"
	"github.com/KusoKaihatsuSha/startup/internal/helpers"
	"github.com/KusoKaihatsuSha/startup/internal/order"
)

var defArgs = os.Args

type Configuration struct {
	TestOrder         string            `json:"test-order"    default:"http://def:81" flag:"to,test,order" env:"TEST_ORDER"    help:"order" valid:"url"`
	TestEmail         string            `json:"test-email"    default:"email"         flag:"test-email"    env:"TEST_EMAIL"    help:"email" valid:"email"`
	TestSlice         []string          `json:"test-slice"    default:"1,2,3,4;5;6"   flag:"test-slice"    env:"TEST_SLICE"    help:"slice" valid:"test"`
	TestInt           int64             `json:"test-int"      default:"11"            flag:"test-int"      env:"TEST_INT"      help:"int"   valid:"max10"`
	TestDuration      time.Duration     `json:"test-duration" default:"1s"            flag:"test-duration" env:"TEST_DURATION" help:"duration"`
	TestBool          bool              `json:"test-bool"     default:"true"          flag:"test-bool"     env:"TEST_BOOL"     help:"bool"`
	TestFloat         float64           `json:"test-float"    default:"1"             flag:"test-float"    env:"TEST_FLOAT"    help:"float"`
	TestUint          uint64            `json:"test-uint"     default:"111"           flag:"test-uint"     env:"TEST_UINT"     help:"uint"`
	TestIP            net.IP            `json:"test-ip"       default:"127.0.0.1"     flag:"test-ip"       env:"TEST_IP"       help:"ip"`
	TestNonMethodJSON TestNonMethodJSON `json:"test-nmj"      default:""              flag:"test-nmj"      env:"TEST_NMJ"      help:"non method json"`
	TestJSON          TestJSON          `json:"test-json"     default:"{\"param1\":\"default_001\",\"param2\":\"default_002\"}" flag:"test-json" env:"TEST_JSON" help:"json"`
}

type TestNonMethodJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

type TestJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (t *TestJSON) UnmarshalText(text []byte) error {
	type Tmp *TestJSON
	if err := json.Unmarshal(text, Tmp(t)); err != nil {
		return err
	}
	return nil
}

func run() {
	startup.DEBUG = true

	startup.GetForce[Configuration]()

	startup.GetForce[Configuration](
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
		order.FILE,
	)
	startup.DEBUG = false
}

func main() {
	os.Args = defArgs
	testDataDef := `{
	             "test-order": "http://config.ini"
	     }`

	fileDef := helpers.CreateFile("config.ini")
	defer helpers.DeleteFile(fileDef)
	err := os.WriteFile(fileDef, []byte(testDataDef), 0755)
	if err != nil {
		fmt.Println(err)
	}

	err = os.Setenv("TEST_ORDER", "http://env")
	if err != nil {
		fmt.Println(err)
	}

	flagVal := "http://flag"
	os.Args = append(
		os.Args,
		"-to="+"http://flag-skip",
		"-test="+flagVal,
	)

	fmt.Printf(
		`
PRESETS
┌──────────────────────────────────────────────────────────────────────────
│                         flag : %s
│                  environment : %s
│                  config file : %s
└──────────────────────────────────────────────────────────────────────────
`,
		flagVal,
		os.Getenv("TEST_ORDER"),
		"config.ini",
	)

	run()

}
Output:

PRESETS
┌──────────────────────────────────────────────────────────────────────────
│                         flag : http://flag
│                  environment : http://env
│                  config file : config.ini
└──────────────────────────────────────────────────────────────────────────
EMPTY - only defaults
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => default config.ini
DATA => {config.ini:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags]
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments]
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => default config.ini
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => default config.ini
DATA => {config.ini:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => default config.ini
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => default config.ini
DATA => {config.ini:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments]
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags]
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags] ↣ [Environments]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => default config.ini
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File] ↣ [Environments]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => default config.ini
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments] ↣ [Flags]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => default config.ini
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File] ↣ [Flags]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => default config.ini
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => default config.ini
DATA => {config.ini:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => default config.ini
DATA => {config.ini:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}
Example (ConfigOrderDef)
package main

import (
	"encoding/json"
	"net"
	"os"
	"time"

	"github.com/KusoKaihatsuSha/startup"
	"github.com/KusoKaihatsuSha/startup/internal/order"
)

var defArgs = os.Args

type Configuration struct {
	TestOrder         string            `json:"test-order"    default:"http://def:81" flag:"to,test,order" env:"TEST_ORDER"    help:"order" valid:"url"`
	TestEmail         string            `json:"test-email"    default:"email"         flag:"test-email"    env:"TEST_EMAIL"    help:"email" valid:"email"`
	TestSlice         []string          `json:"test-slice"    default:"1,2,3,4;5;6"   flag:"test-slice"    env:"TEST_SLICE"    help:"slice" valid:"test"`
	TestInt           int64             `json:"test-int"      default:"11"            flag:"test-int"      env:"TEST_INT"      help:"int"   valid:"max10"`
	TestDuration      time.Duration     `json:"test-duration" default:"1s"            flag:"test-duration" env:"TEST_DURATION" help:"duration"`
	TestBool          bool              `json:"test-bool"     default:"true"          flag:"test-bool"     env:"TEST_BOOL"     help:"bool"`
	TestFloat         float64           `json:"test-float"    default:"1"             flag:"test-float"    env:"TEST_FLOAT"    help:"float"`
	TestUint          uint64            `json:"test-uint"     default:"111"           flag:"test-uint"     env:"TEST_UINT"     help:"uint"`
	TestIP            net.IP            `json:"test-ip"       default:"127.0.0.1"     flag:"test-ip"       env:"TEST_IP"       help:"ip"`
	TestNonMethodJSON TestNonMethodJSON `json:"test-nmj"      default:""              flag:"test-nmj"      env:"TEST_NMJ"      help:"non method json"`
	TestJSON          TestJSON          `json:"test-json"     default:"{\"param1\":\"default_001\",\"param2\":\"default_002\"}" flag:"test-json" env:"TEST_JSON" help:"json"`
}

type TestNonMethodJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

type TestJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (t *TestJSON) UnmarshalText(text []byte) error {
	type Tmp *TestJSON
	if err := json.Unmarshal(text, Tmp(t)); err != nil {
		return err
	}
	return nil
}

func run() {
	startup.DEBUG = true

	startup.GetForce[Configuration]()

	startup.GetForce[Configuration](
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
		order.FILE,
	)
	startup.DEBUG = false
}

func main() {
	os.Args = defArgs
	run()

}
Output:

EMPTY - only defaults
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags]
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments]
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments]
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags]
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags] ↣ [Environments]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File] ↣ [Environments]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments] ↣ [Flags]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File] ↣ [Flags]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}
Example (ConfigOrderFlagEnv)
package main

import (
	"encoding/json"
	"fmt"
	"net"
	"os"
	"time"

	"github.com/KusoKaihatsuSha/startup"
	"github.com/KusoKaihatsuSha/startup/internal/order"
)

var defArgs = os.Args

type Configuration struct {
	TestOrder         string            `json:"test-order"    default:"http://def:81" flag:"to,test,order" env:"TEST_ORDER"    help:"order" valid:"url"`
	TestEmail         string            `json:"test-email"    default:"email"         flag:"test-email"    env:"TEST_EMAIL"    help:"email" valid:"email"`
	TestSlice         []string          `json:"test-slice"    default:"1,2,3,4;5;6"   flag:"test-slice"    env:"TEST_SLICE"    help:"slice" valid:"test"`
	TestInt           int64             `json:"test-int"      default:"11"            flag:"test-int"      env:"TEST_INT"      help:"int"   valid:"max10"`
	TestDuration      time.Duration     `json:"test-duration" default:"1s"            flag:"test-duration" env:"TEST_DURATION" help:"duration"`
	TestBool          bool              `json:"test-bool"     default:"true"          flag:"test-bool"     env:"TEST_BOOL"     help:"bool"`
	TestFloat         float64           `json:"test-float"    default:"1"             flag:"test-float"    env:"TEST_FLOAT"    help:"float"`
	TestUint          uint64            `json:"test-uint"     default:"111"           flag:"test-uint"     env:"TEST_UINT"     help:"uint"`
	TestIP            net.IP            `json:"test-ip"       default:"127.0.0.1"     flag:"test-ip"       env:"TEST_IP"       help:"ip"`
	TestNonMethodJSON TestNonMethodJSON `json:"test-nmj"      default:""              flag:"test-nmj"      env:"TEST_NMJ"      help:"non method json"`
	TestJSON          TestJSON          `json:"test-json"     default:"{\"param1\":\"default_001\",\"param2\":\"default_002\"}" flag:"test-json" env:"TEST_JSON" help:"json"`
}

type TestNonMethodJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

type TestJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (t *TestJSON) UnmarshalText(text []byte) error {
	type Tmp *TestJSON
	if err := json.Unmarshal(text, Tmp(t)); err != nil {
		return err
	}
	return nil
}

func run() {
	startup.DEBUG = true

	startup.GetForce[Configuration]()

	startup.GetForce[Configuration](
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
		order.FILE,
	)
	startup.DEBUG = false
}

func main() {
	os.Args = defArgs
	err := os.Setenv("TEST_ORDER", "http://env")
	if err != nil {
		fmt.Println(err)
	}

	flagVal := "http://flag"
	os.Args = append(
		os.Args,
		"-to="+"http://flag-skip",
		"-test="+flagVal,
	)

	fmt.Printf(
		`
PRESETS
┌──────────────────────────────────────────────────────────────────────────
│                         flag : %s
│                  environment : %s
└──────────────────────────────────────────────────────────────────────────
`,
		flagVal,
		os.Getenv("TEST_ORDER"),
	)

	run()

}
Output:

PRESETS
┌──────────────────────────────────────────────────────────────────────────
│                         flag : http://flag
│                  environment : http://env
└──────────────────────────────────────────────────────────────────────────
EMPTY - only defaults
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags]
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments]
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments]
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags]
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags] ↣ [Environments]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File] ↣ [Environments]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments] ↣ [Flags]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File] ↣ [Flags]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags] ↣ [JSON File]
	info about config file:	Environment 'CONFIG' with filepath not set
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}
Example (ConfigOrderManyConfFlagEnv)
package main

import (
	"encoding/json"
	"fmt"
	"net"
	"os"
	"strings"
	"time"

	"github.com/KusoKaihatsuSha/startup"
	"github.com/KusoKaihatsuSha/startup/internal/helpers"
	"github.com/KusoKaihatsuSha/startup/internal/order"
)

var defArgs = os.Args

type Configuration struct {
	TestOrder         string            `json:"test-order"    default:"http://def:81" flag:"to,test,order" env:"TEST_ORDER"    help:"order" valid:"url"`
	TestEmail         string            `json:"test-email"    default:"email"         flag:"test-email"    env:"TEST_EMAIL"    help:"email" valid:"email"`
	TestSlice         []string          `json:"test-slice"    default:"1,2,3,4;5;6"   flag:"test-slice"    env:"TEST_SLICE"    help:"slice" valid:"test"`
	TestInt           int64             `json:"test-int"      default:"11"            flag:"test-int"      env:"TEST_INT"      help:"int"   valid:"max10"`
	TestDuration      time.Duration     `json:"test-duration" default:"1s"            flag:"test-duration" env:"TEST_DURATION" help:"duration"`
	TestBool          bool              `json:"test-bool"     default:"true"          flag:"test-bool"     env:"TEST_BOOL"     help:"bool"`
	TestFloat         float64           `json:"test-float"    default:"1"             flag:"test-float"    env:"TEST_FLOAT"    help:"float"`
	TestUint          uint64            `json:"test-uint"     default:"111"           flag:"test-uint"     env:"TEST_UINT"     help:"uint"`
	TestIP            net.IP            `json:"test-ip"       default:"127.0.0.1"     flag:"test-ip"       env:"TEST_IP"       help:"ip"`
	TestNonMethodJSON TestNonMethodJSON `json:"test-nmj"      default:""              flag:"test-nmj"      env:"TEST_NMJ"      help:"non method json"`
	TestJSON          TestJSON          `json:"test-json"     default:"{\"param1\":\"default_001\",\"param2\":\"default_002\"}" flag:"test-json" env:"TEST_JSON" help:"json"`
}

type TestNonMethodJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

type TestJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (t *TestJSON) UnmarshalText(text []byte) error {
	type Tmp *TestJSON
	if err := json.Unmarshal(text, Tmp(t)); err != nil {
		return err
	}
	return nil
}

func run() {
	startup.DEBUG = true

	startup.GetForce[Configuration]()

	startup.GetForce[Configuration](
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
		order.FILE,
	)
	startup.DEBUG = false
}

func main() {
	os.Args = defArgs
	testDataDef := `{
	             "test-order": "http://config.ini"
	     }`
	testDataFlag := `{
                 "test-order": "http://file-flag"
         }`
	testDataEnv := `{
                 "test-order": "http://file-env"
         }`
	fileDef := helpers.CreateFile("config.ini")
	defer helpers.DeleteFile(fileDef)
	err := os.WriteFile(fileDef, []byte(testDataDef), 0755)
	if err != nil {
		fmt.Println(err)
	}

	fileFlag := helpers.ValidTempFile("file-flag.confile")
	defer helpers.DeleteFile(fileFlag)
	err = os.WriteFile(fileFlag, []byte(testDataFlag), 0755)
	if err != nil {
		fmt.Println(err)
	}

	fileEnv := helpers.ValidTempFile("file-env.confile")
	defer helpers.DeleteFile(fileEnv)
	err = os.WriteFile(fileEnv, []byte(testDataEnv), 0755)
	if err != nil {
		fmt.Println(err)
	}

	err = os.Setenv("TEST_ORDER", "http://env")
	if err != nil {
		fmt.Println(err)
	}

	err = os.Setenv("CONFIG", fileEnv)
	if err != nil {
		fmt.Println(err)
	}
	flagVal := "http://flag"
	os.Args = append(
		os.Args,
		"-config="+fileFlag,
		"-to="+"http://flag-skip",
		"-test="+flagVal,
	)

	fmt.Printf(
		`
PRESETS
┌──────────────────────────────────────────────────────────────────────────
│                         flag : %s
│                  environment : %s
│   config-file in environment : %s
│          config-file in flag : %s
│              def config-file : %s
└──────────────────────────────────────────────────────────────────────────
`,
		flagVal,
		os.Getenv("TEST_ORDER"),
		strings.ReplaceAll(strings.ReplaceAll(testDataEnv, " ", ""), string([]rune{10}), ""),
		strings.ReplaceAll(strings.ReplaceAll(testDataFlag, " ", ""), string([]rune{10}), ""),
		"config.ini",
	)

	run()

}
Output:

PRESETS
┌──────────────────────────────────────────────────────────────────────────
│                         flag : http://flag
│                  environment : http://env
│   config-file in environment : {"test-order":"http://file-env"}
│          config-file in flag : {"test-order":"http://file-flag"}
│              def config-file : config.ini
└──────────────────────────────────────────────────────────────────────────
EMPTY - only defaults
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {file-flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags]
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments]
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {file-flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {file-env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments]
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags]
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags] ↣ [Environments]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File] ↣ [Environments]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments] ↣ [Flags]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File] ↣ [Flags]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {file-env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {file-flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}
Example (ConfigOrderOtherConfFlagEnv)
package main

import (
	"encoding/json"
	"fmt"
	"net"
	"os"
	"strings"
	"time"

	"github.com/KusoKaihatsuSha/startup"
	"github.com/KusoKaihatsuSha/startup/internal/helpers"
	"github.com/KusoKaihatsuSha/startup/internal/order"
)

var defArgs = os.Args

type Configuration struct {
	TestOrder         string            `json:"test-order"    default:"http://def:81" flag:"to,test,order" env:"TEST_ORDER"    help:"order" valid:"url"`
	TestEmail         string            `json:"test-email"    default:"email"         flag:"test-email"    env:"TEST_EMAIL"    help:"email" valid:"email"`
	TestSlice         []string          `json:"test-slice"    default:"1,2,3,4;5;6"   flag:"test-slice"    env:"TEST_SLICE"    help:"slice" valid:"test"`
	TestInt           int64             `json:"test-int"      default:"11"            flag:"test-int"      env:"TEST_INT"      help:"int"   valid:"max10"`
	TestDuration      time.Duration     `json:"test-duration" default:"1s"            flag:"test-duration" env:"TEST_DURATION" help:"duration"`
	TestBool          bool              `json:"test-bool"     default:"true"          flag:"test-bool"     env:"TEST_BOOL"     help:"bool"`
	TestFloat         float64           `json:"test-float"    default:"1"             flag:"test-float"    env:"TEST_FLOAT"    help:"float"`
	TestUint          uint64            `json:"test-uint"     default:"111"           flag:"test-uint"     env:"TEST_UINT"     help:"uint"`
	TestIP            net.IP            `json:"test-ip"       default:"127.0.0.1"     flag:"test-ip"       env:"TEST_IP"       help:"ip"`
	TestNonMethodJSON TestNonMethodJSON `json:"test-nmj"      default:""              flag:"test-nmj"      env:"TEST_NMJ"      help:"non method json"`
	TestJSON          TestJSON          `json:"test-json"     default:"{\"param1\":\"default_001\",\"param2\":\"default_002\"}" flag:"test-json" env:"TEST_JSON" help:"json"`
}

type TestNonMethodJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

type TestJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (t *TestJSON) UnmarshalText(text []byte) error {
	type Tmp *TestJSON
	if err := json.Unmarshal(text, Tmp(t)); err != nil {
		return err
	}
	return nil
}

func run() {
	startup.DEBUG = true

	startup.GetForce[Configuration]()

	startup.GetForce[Configuration](
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
		order.FILE,
	)
	startup.DEBUG = false
}

func main() {
	os.Args = defArgs
	testDataFlag := `{
                 "test-order": "http://file-flag"
         }`
	testDataEnv := `{
                 "test-order": "http://file-env"
         }`

	fileFlag := helpers.ValidTempFile("file-flag.confile")
	defer helpers.DeleteFile(fileFlag)
	err := os.WriteFile(fileFlag, []byte(testDataFlag), 0755)
	if err != nil {
		fmt.Println(err)
	}

	fileEnv := helpers.ValidTempFile("file-env.confile")
	defer helpers.DeleteFile(fileEnv)
	err = os.WriteFile(fileEnv, []byte(testDataEnv), 0755)
	if err != nil {
		fmt.Println(err)
	}

	err = os.Setenv("TEST_ORDER", "http://env")
	if err != nil {
		fmt.Println(err)
	}

	err = os.Setenv("CONFIG", fileEnv)
	if err != nil {
		fmt.Println(err)
	}
	flagVal := "http://flag"
	os.Args = append(
		os.Args,
		"-config="+fileFlag,
		"-to="+"http://flag-skip",
		"-test="+flagVal,
	)

	fmt.Printf(
		`
PRESETS
┌──────────────────────────────────────────────────────────────────────────
│                         flag : %s
│                  environment : %s
│   config-file in environment : %s
│          config-file in flag : %s
└──────────────────────────────────────────────────────────────────────────
`,
		flagVal,
		os.Getenv("TEST_ORDER"),
		strings.ReplaceAll(strings.ReplaceAll(testDataEnv, " ", ""), string([]rune{10}), ""),
		strings.ReplaceAll(strings.ReplaceAll(testDataFlag, " ", ""), string([]rune{10}), ""),
	)

	run()

}
Output:

PRESETS
┌──────────────────────────────────────────────────────────────────────────
│                         flag : http://flag
│                  environment : http://env
│   config-file in environment : {"test-order":"http://file-env"}
│          config-file in flag : {"test-order":"http://file-flag"}
└──────────────────────────────────────────────────────────────────────────
EMPTY - only defaults
DATA => {def:81 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {file-flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags]
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments]
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {file-flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {file-env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments]
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags]
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags] ↣ [Environments]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File] ↣ [Environments]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments] ↣ [Flags]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File] ↣ [Flags]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {file-env:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Get filepath from flag '-config'
FILE => file-flag.confile
DATA => {file-flag:80 email [] 11 1s true 1 111 127.0.0.1 { } {default_001 default_002}}
Example (ConfigOrigin)
package main

import (
	"encoding/json"
	"fmt"
	"net"
	"os"
	"regexp"
	"strings"
	"time"

	"github.com/KusoKaihatsuSha/startup"
	"github.com/KusoKaihatsuSha/startup/internal/helpers"
	"github.com/KusoKaihatsuSha/startup/internal/order"
)

var defArgs = os.Args

type Configuration struct {
	TestOrder         string            `json:"test-order"    default:"http://def:81" flag:"to,test,order" env:"TEST_ORDER"    help:"order" valid:"url"`
	TestEmail         string            `json:"test-email"    default:"email"         flag:"test-email"    env:"TEST_EMAIL"    help:"email" valid:"email"`
	TestSlice         []string          `json:"test-slice"    default:"1,2,3,4;5;6"   flag:"test-slice"    env:"TEST_SLICE"    help:"slice" valid:"test"`
	TestInt           int64             `json:"test-int"      default:"11"            flag:"test-int"      env:"TEST_INT"      help:"int"   valid:"max10"`
	TestDuration      time.Duration     `json:"test-duration" default:"1s"            flag:"test-duration" env:"TEST_DURATION" help:"duration"`
	TestBool          bool              `json:"test-bool"     default:"true"          flag:"test-bool"     env:"TEST_BOOL"     help:"bool"`
	TestFloat         float64           `json:"test-float"    default:"1"             flag:"test-float"    env:"TEST_FLOAT"    help:"float"`
	TestUint          uint64            `json:"test-uint"     default:"111"           flag:"test-uint"     env:"TEST_UINT"     help:"uint"`
	TestIP            net.IP            `json:"test-ip"       default:"127.0.0.1"     flag:"test-ip"       env:"TEST_IP"       help:"ip"`
	TestNonMethodJSON TestNonMethodJSON `json:"test-nmj"      default:""              flag:"test-nmj"      env:"TEST_NMJ"      help:"non method json"`
	TestJSON          TestJSON          `json:"test-json"     default:"{\"param1\":\"default_001\",\"param2\":\"default_002\"}" flag:"test-json" env:"TEST_JSON" help:"json"`
}

type TestNonMethodJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

type TestJSON struct {
	P1 string `json:"param1"`
	P2 string `json:"param2"`
}

// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (t *TestJSON) UnmarshalText(text []byte) error {
	type Tmp *TestJSON
	if err := json.Unmarshal(text, Tmp(t)); err != nil {
		return err
	}
	return nil
}

// custom email validation
type emailValid string

var emailValidation emailValid = "email"

func (o emailValid) Valid(stringValue string, value any) (any, bool) {
	matchString, err := regexp.MatchString("(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])", stringValue)
	if matchString && err == nil {
		return value, true
	}
	return stringValue + "@example.com", true
}

// custom slice validation
type testValid string

var testValidation testValid = "test"

func (o testValid) Valid(stringValue string, value any) (any, bool) {

	newValue := strings.ReplaceAll(stringValue, ";", ",")
	return strings.Split(newValue, ","), true
}

// custom max10 validation
type maxValid string

var maxValidation maxValid = "max10"

func (o maxValid) Valid(stringValue string, value any) (any, bool) {
	if value.(int64) > 10 {
		return int64(10), true
	}
	return value, true
}

func runNoPreload() {
	startup.DEBUG = true

	startup.GetForce[Configuration](order.NoPreloadConfig)

	startup.GetForce[Configuration](
		order.FILE,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.NoPreloadConfig,
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.NoPreloadConfig,
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
		order.ENV,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
		order.ENV,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
		order.FLAG,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
		order.FLAG,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
		order.FILE,
		order.NoPreloadConfig,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
		order.FILE,
		order.NoPreloadConfig,
	)
}

func run() {
	startup.DEBUG = true

	startup.GetForce[Configuration]()

	startup.GetForce[Configuration](
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.FLAG,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.FILE,
		order.ENV,
	)

	startup.GetForce[Configuration](
		order.FILE,
		order.ENV,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FILE,
		order.FLAG,
	)

	startup.GetForce[Configuration](
		order.FLAG,
		order.ENV,
		order.FILE,
	)

	startup.GetForce[Configuration](
		order.ENV,
		order.FLAG,
		order.FILE,
	)
	startup.DEBUG = false
}

func main() {
	os.Args = defArgs

	startup.AddValidation(testValidation)
	startup.AddValidation(emailValidation)
	startup.AddValidation(maxValidation)

	err := os.Setenv("TEST_SLICE", "999")
	if err != nil {
		fmt.Println(err)
	}

	os.Args = append(
		os.Args,
		"-test-email="+"flag@email.post",
		"-test-int="+"100",
		"-test-slice="+"100,200,300",
		"-test-json="+"{\"param1\":\"new_003\",\"param2\":\"new_004\"}",
	)

	testDataEnv := `{
                 "test-email": "fileenv@mail.com",
                 "test-slice": "18,19,20"
         }`

	fileEnv := helpers.ValidTempFile("test.confile")
	defer helpers.DeleteFile(fileEnv)
	err = os.WriteFile(fileEnv, []byte(testDataEnv), 0755)
	if err != nil {
		fmt.Println(err)
	}
	err = os.Setenv("CONFIG", fileEnv)
	if err != nil {
		fmt.Println(err)
	}

	run()
	runNoPreload()

}
Output:

EMPTY - only defaults
DATA => {def:81 email@example.com [1 2 3 4 5 6] 10 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {def:81 fileenv@mail.com [18 19 20] 10 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags]
DATA => {def:81 flag@email.post [100 200 300] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments]
DATA => {env:80 email@example.com [999] 10 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {def:81 flag@email.post [100 200 300] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {def:81 fileenv@mail.com [18 19 20] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {env:80 fileenv@mail.com [999] 10 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {env:80 fileenv@mail.com [18 19 20] 10 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments]
DATA => {env:80 flag@email.post [999] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags]
DATA => {env:80 flag@email.post [100 200 300] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Flags] ↣ [Environments]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {env:80 flag@email.post [999] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [JSON File] ↣ [Environments]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {env:80 fileenv@mail.com [999] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[JSON File] ↣ [Environments] ↣ [Flags]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {env:80 flag@email.post [100 200 300] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [JSON File] ↣ [Flags]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {env:80 flag@email.post [100 200 300] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Flags] ↣ [Environments] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {env:80 fileenv@mail.com [18 19 20] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

PreloadConfigEnvThenFlag/Default - Preload find config in Env then Flag
Structure filling order:
	[Environments] ↣ [Flags] ↣ [JSON File]
	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {env:80 fileenv@mail.com [18 19 20] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
DATA => {def:81 email@example.com [1 2 3 4 5 6] 10 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[JSON File] ↣ FILE => not any config file
DATA => {def:81 email@example.com [1 2 3 4 5 6] 10 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[Flags] ↣ DATA => {def:81 flag@email.post [100 200 300] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[Environments] ↣ DATA => {env:80 email@example.com [999] 10 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
[JSON File] ↣ [Flags]
	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 flag@email.post [100 200 300] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[Flags] ↣ [JSON File] ↣ 	info about config file:	Flag '-config' with filepath not set
FILE => not any config file
DATA => {def:81 flag@email.post [100 200 300] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
[JSON File] ↣ [Environments]
	info about config file:	Get filepath from environment 'CONFIG'
FILE => test.confile
DATA => {env:80 fileenv@mail.com [999] 10 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[Environments] ↣ [JSON File] ↣ 	info about config file:	Get filepath from environment 'CONFIG'
FILE => test.confile
DATA => {env:80 fileenv@mail.com [18 19 20] 10 1s true 1 111 127.0.0.1 { } {default_001 default_002}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[Flags] ↣ [Environments] ↣ DATA => {env:80 flag@email.post [999] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[Environments] ↣ [Flags] ↣ DATA => {env:80 flag@email.post [100 200 300] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[JSON File] ↣ [Flags] ↣ [Environments] ↣ 	info about config file:	Flag '-config' with filepath not set
	info about config file:	Get filepath from environment 'CONFIG'
FILE => test.confile
DATA => {env:80 flag@email.post [999] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[Flags] ↣ [JSON File] ↣ [Environments] ↣ 	info about config file:	Flag '-config' with filepath not set
	info about config file:	Get filepath from environment 'CONFIG'
FILE => test.confile
DATA => {env:80 fileenv@mail.com [999] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[JSON File] ↣ [Environments] ↣ [Flags] ↣ 	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {env:80 flag@email.post [100 200 300] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[Environments] ↣ [JSON File] ↣ [Flags] ↣ 	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {env:80 flag@email.post [100 200 300] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[Flags] ↣ [Environments] ↣ [JSON File] ↣ 	info about config file:	Flag '-config' with filepath not set
	info about config file:	Get filepath from environment 'CONFIG'
FILE => test.confile
DATA => {env:80 fileenv@mail.com [18 19 20] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

NoPreloadConfig - Disable find config in other places. Only in list
Structure filling order:
	[Environments] ↣ [Flags] ↣ [JSON File] ↣ 	info about config file:	Get filepath from environment 'CONFIG'
	info about config file:	Flag '-config' with filepath not set
FILE => test.confile
DATA => {env:80 fileenv@mail.com [18 19 20] 10 1s true 1 111 127.0.0.1 { } {new_003 new_004}}

Index

Examples

Constants

View Source
const (
	// FLAG Get data from flags
	FLAG = order.FLAG

	// FILE Get data from json file
	FILE = order.FILE

	// ENV Get data from environments
	ENV = order.ENV

	// PreloadConfigEnvThenFlag - Get filepath config from environments and then flags
	// Default
	PreloadConfigEnvThenFlag = order.PreloadConfigEnvThenFlag

	// PreloadConfigFlagThenEnv - Get filepath config from flags and then environments
	PreloadConfigFlagThenEnv = order.PreloadConfigFlagThenEnv

	// PreloadConfigFlag - Get filepath config from flags
	PreloadConfigFlag = order.PreloadConfigFlag

	// PreloadConfigEnv - Get filepath config from environments
	PreloadConfigEnv = order.PreloadConfigEnv

	// NoPreloadConfig - Get filepath config file only from ordered stages
	NoPreloadConfig = order.NoPreloadConfig
)

Variables

View Source
var DEBUG = false

Functions

func AddValidation

func AddValidation(value ...validation.Valid)

AddValidation using for add custom validation

Example:

	// Custom struct. Struct will be implement in program with selected 'Stages' variable.
	type Test struct {
		NewValid []string `json:"new-valid" default:"new valid is default" flag:"valid" text:"-" valid:"test"`
	}
	// Custom type.
	type testValid string
	// Custom validation.
	var testValidation testValid = "test"
	// Custom method.
	func (o testValid) Valid(stringValue string, value any) (any, bool) {
		return []string{stringValue + "+++"}, true
	}

    // add custom validation
	func MyFunc() {
		...
		startup.AddValidation(testValidation)
		...
		// Implement all types of configs (Json file -> Environment -> Flags).
		configurations := startup.Get[Test](startup.FILE, startup.ENV, startup.FLAG)
		// Test print.
		fmt.Println(configurations)
	}

Default validations:

  • `tmp_file` - Check exist inside Temp folder and create if not exist (string in struct)
  • `file` - Check exist the filepath and create if not exist (string in struct)
  • `url` - Check url is correct (string in struct)
  • `bool` - Parse Bool (bool in struct)
  • `int` - Parse int (int64 in struct)
  • `float` - Parse float (float64 in struct)
  • `duration` - Parse duration (time.Duration in struct)
  • `uuid` - Check uuid. Return new if not exist (string in struct)

Caution: flags are reserved:

  • config

func Get

func Get[T any](stages ...order.Stages) T

Get will initialize scan the flags(one time), environment and config-file with the right order:

  • order.FLAG - flag
  • order.FILE - config file
  • order.ENV - environment

Caution! flags are reserved:

  • config

func GetForce

func GetForce[T any](stages ...order.Stages) T

GetForce will initialize scan the flags, environment and config-file with the right order:

  • order.FLAG - flag
  • order.FILE - config file
  • order.ENV - environment

Caution! flags are reserved:

  • config

Types

This section is empty.

Directories

Path Synopsis
internal
helpers
Package helpers working with logging and other non-main/other help-function.
Package helpers working with logging and other non-main/other help-function.
tag

Jump to

Keyboard shortcuts

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