koanf

2025-12-11 0 1,002

koanf是一个库,用于在GO应用程序中以不同格式的不同来源读取配置。它是SPF13/Viper的更清洁,更轻松的替代品,具有更好的抽象和可扩展性,依赖性较少。

koanf V2具有用于从各种来源读取配置的模块(提供商),例如文件,命令线标志,环境变量,库库和S3,以及用于解析(解析器)格式,例如JSON,YAML,TOML,TOML,Hashicorp HCl。很容易插入自定义解析器和提供商。

提供者和解析器中的所有外部依赖项均与核心分离,并且可以根据需要单独安装

安装

koanf/v2

# Install the necessary Provider(s).
# Available: file, env/v2, posflag, basicflag, confmap, rawbytes,
# structs, fs, s3, appconfig/v2, consul/v2, etcd/v2, vault/v2, parameterstore/v2
# eg: go get -u github.com/knadh/ koanf /providers/s3
# eg: go get -u github.com/knadh/ koanf /providers/consul/v2

go get -u github.com/knadh/ koanf /providers/file

# Install the necessary Parser(s).
# Available: toml, toml/v2, json, yaml, dotenv, hcl, hjson, nestedtext
# go get -u github.com/knadh/ koanf /parsers/$parser

go get -u github.com/knadh/ koanf /parsers/toml\”>

 # Install the core.
go get -u github.com/knadh/ koanf /v2

# Install the necessary Provider(s).
# Available: file, env/v2, posflag, basicflag, confmap, rawbytes,
#            structs, fs, s3, appconfig/v2, consul/v2, etcd/v2, vault/v2, parameterstore/v2
# eg: go get -u github.com/knadh/ koanf /providers/s3
# eg: go get -u github.com/knadh/ koanf /providers/consul/v2

go get -u github.com/knadh/ koanf /providers/file


# Install the necessary Parser(s).
# Available: toml, toml/v2, json, yaml, dotenv, hcl, hjson, nestedtext
# go get -u github.com/knadh/ koanf /parsers/$parser

go get -u github.com/knadh/ koanf /parsers/toml

请参阅所有捆绑的提供商和解析器的列表。

内容

  • 概念
  • 从文件读取配置
  • 观看文件以进行更改
  • 从命令行读取
  • 阅读环境变量
  • 读取原始字节
  • 从地图和结构阅读
  • 解除和编组
  • 合并和关键案例灵敏度的顺序
  • 定制提供商和解析器
  • 定制合并策略
  • 可安装的提供商和解析器列表

概念

  • koanf .Provider是一个通用接口,可提供配置,例如,来自文件,环境变量,HTTP源或任何地方。配置可以是解析器可以解析的原始字节,也可以是可以直接加载的嵌套map[string]interface{}
  • koanf .Parser是一个通用接口,可以采用原始字节,解析并返回一个嵌套的map[string]interface{} 。例如,JSON和YAML解析器。
  • 一旦加载到koanf中,配置就会由界定的关键路径语法查询。例如: app.server.port 。可以选择任何定界符。
  • 可以将来自多个源的配置加载并合并到koanf实例中,例如,首先从文件加载,并用命令行的标志覆盖某些值。

通过这两个接口实现, koanf可以从任何源以任何格式获得配置,并将其解析,并使应用程序可用于应用程序。

从文件读取配置

koanf/v2\”
\”github.com/knadh/ koanf /parsers/json\”
\”github.com/knadh/ koanf /parsers/yaml\”
\”github.com/knadh/ koanf /providers/file\”
)

// Global koanf instance. Use \”.\” as the key path delimiter. This can be \”/\” or any character.
var k = koanf .New(\”.\”)

func main() {
// Load JSON config.
if err := k.Load(file.Provider(\”mock/mock.json\”), json.Parser()); err != nil {
log.Fatalf(\”error loading config: %v\”, err)
}

// Load YAML config and merge into the previously loaded config (because we can).
k.Load(file.Provider(\”mock/mock.yml\”), yaml.Parser())

fmt.Println(\”parent\’s name is = \”, k.String(\”parent1.name\”))
fmt.Println(\”parent\’s ID is = \”, k.Int(\”parent1.id\”))
}
\”>

 package main

import (
	\"fmt\"
	\"log\"

	\"github.com/knadh/ koanf /v2\"
	\"github.com/knadh/ koanf /parsers/json\"
	\"github.com/knadh/ koanf /parsers/yaml\"
	\"github.com/knadh/ koanf /providers/file\"
)

// Global koanf instance. Use \".\" as the key path delimiter. This can be \"/\" or any character.
var k = koanf . New ( \".\" )

func main () {
	// Load JSON config.
	if err := k . Load ( file . Provider ( \"mock/mock.json\" ), json . Parser ()); err != nil {
		log . Fatalf ( \"error loading config: %v\" , err )
	}

	// Load YAML config and merge into the previously loaded config (because we can).
	k . Load ( file . Provider ( \"mock/mock.yml\" ), yaml . Parser ())

	fmt . Println ( \"parent\'s name is = \" , k . String ( \"parent1.name\" ))
	fmt . Println ( \"parent\'s ID is = \" , k . Int ( \"parent1.id\" ))
}

观看文件以进行更改

一些提供商揭示了一种Watch()方法,该方法使提供商手表更改配置并触发回调以重新加载配置。如果在koanf对象上执行Load()时发生同时发生的*Get()调用,这不是goroutine安全的。这种情况将需要静音锁定。

file, appconfig, vault, consul提供商具有Watch()方法。

koanf/v2\”
\”github.com/knadh/ koanf /parsers/json\”
\”github.com/knadh/ koanf /parsers/yaml\”
\”github.com/knadh/ koanf /providers/file\”
)

// Global koanf instance. Use \”.\” as the key path delimiter. This can be \”/\” or any character.
var k = koanf .New(\”.\”)

func main() {
// Load JSON config.
f := file.Provider(\”mock/mock.json\”)
if err := k.Load(f, json.Parser()); err != nil {
log.Fatalf(\”error loading config: %v\”, err)
}

// Load YAML config and merge into the previously loaded config (because we can).
k.Load(file.Provider(\”mock/mock.yml\”), yaml.Parser())

fmt.Println(\”parent\’s name is = \”, k.String(\”parent1.name\”))
fmt.Println(\”parent\’s ID is = \”, k.Int(\”parent1.id\”))

// Watch the file and get a callback on change. The callback can do whatever,
// like re-load the configuration.
// File provider always returns a nil `event`.
f.Watch(func(event interface{}, err error) {
if err != nil {
log.Printf(\”watch error: %v\”, err)
return
}

// Throw away the old config and load a fresh copy.
log.Println(\”config changed. Reloading …\”)
k = koanf .New(\”.\”)
k.Load(f, json.Parser())
k.Print()
})

// To stop a file watcher, call:
// f.Unwatch()

// Block forever (and manually make a change to mock/mock.json) to
// reload the config.
log.Println(\”waiting forever. Try making a change to mock/mock.json to live reload\”)
<-make(chan bool)
}\”>

 package main

import (
	\"fmt\"
	\"log\"

	\"github.com/knadh/ koanf /v2\"
	\"github.com/knadh/ koanf /parsers/json\"
	\"github.com/knadh/ koanf /parsers/yaml\"
	\"github.com/knadh/ koanf /providers/file\"
)

// Global koanf instance. Use \".\" as the key path delimiter. This can be \"/\" or any character.
var k = koanf . New ( \".\" )

func main () {
	// Load JSON config.
	f := file . Provider ( \"mock/mock.json\" )
	if err := k . Load ( f , json . Parser ()); err != nil {
		log . Fatalf ( \"error loading config: %v\" , err )
	}

	// Load YAML config and merge into the previously loaded config (because we can).
	k . Load ( file . Provider ( \"mock/mock.yml\" ), yaml . Parser ())

	fmt . Println ( \"parent\'s name is = \" , k . String ( \"parent1.name\" ))
	fmt . Println ( \"parent\'s ID is = \" , k . Int ( \"parent1.id\" ))

	// Watch the file and get a callback on change. The callback can do whatever,
	// like re-load the configuration.
	// File provider always returns a nil `event`.
	f . Watch ( func ( event interface {}, err error ) {
		if err != nil {
			log . Printf ( \"watch error: %v\" , err )
			return
		}

		// Throw away the old config and load a fresh copy.
		log . Println ( \"config changed. Reloading ...\" )
		k = koanf . New ( \".\" )
		k . Load ( f , json . Parser ())
		k . Print ()
	})

	// To stop a file watcher, call:
	// f.Unwatch()

	// Block forever (and manually make a change to mock/mock.json) to
	// reload the config.
	log . Println ( \"waiting forever. Try making a change to mock/mock.json to live reload\" )
	<- make ( chan bool )
}

从命令行读取

下面的示例显示了posflag.Provider的使用,这是一个由SPF13/PFLAG库(高级命令行Lib)上的包装器。对于GO内置的flag软件包,请使用basicflag.Provider

koanf/v2\”
\”github.com/knadh/ koanf /parsers/toml\”

// TOML version 2 is available at:
// \”github.com/knadh/ koanf /parsers/toml/v2\”

\”github.com/knadh/ koanf /providers/file\”
\”github.com/knadh/ koanf /providers/posflag\”
flag \”github.com/spf13/pflag\”
)

// Global koanf instance. Use \”.\” as the key path delimiter. This can be \”/\” or any character.
var k = koanf .New(\”.\”)

func main() {
// Use the POSIX compliant pflag lib instead of Go\’s flag lib.
f := flag.NewFlagSet(\”config\”, flag.ContinueOnError)
f.Usage = func() {
fmt.Println(f.FlagUsages())
os.Exit(0)
}
// Path to one or more config files to load into koanf along with some config params.
f.StringSlice(\”conf\”, []string{\”mock/mock.toml\”}, \”path to one or more .toml config files\”)
f.String(\”time\”, \”2020-01-01\”, \”a time string\”)
f.String(\”type\”, \”xxx\”, \”type of the app\”)
f.Parse(os.Args[1:])

// Load the config files provided in the commandline.
cFiles, _ := f.GetStringSlice(\”conf\”)
for _, c := range cFiles {
if err := k.Load(file.Provider(c), toml.Parser()); err != nil {
log.Fatalf(\”error loading file: %v\”, err)
}
}

// \”time\” and \”type\” may have been loaded from the config file, but
// they can still be overridden with the values from the command line.
// The bundled posflag.Provider takes a flagset from the spf13/pflag lib.
// Passing the koanf instance to posflag helps it deal with default command
// line flag values that are not present in conf maps from previously loaded
// providers.
if err := k.Load(posflag.Provider(f, \”.\”, k), nil); err != nil {
log.Fatalf(\”error loading config: %v\”, err)
}

fmt.Println(\”time is = \”, k.String(\”time\”))
}\”>

 package main

import (
	\"fmt\"
	\"log\"
	\"os\"

	\"github.com/knadh/ koanf /v2\"
	\"github.com/knadh/ koanf /parsers/toml\"

	// TOML version 2 is available at:
	// \"github.com/knadh/ koanf /parsers/toml/v2\"

	\"github.com/knadh/ koanf /providers/file\"
	\"github.com/knadh/ koanf /providers/posflag\"
	flag \"github.com/spf13/pflag\"
)

// Global koanf instance. Use \".\" as the key path delimiter. This can be \"/\" or any character.
var k = koanf . New ( \".\" )

func main () {
	// Use the POSIX compliant pflag lib instead of Go\'s flag lib.
	f := flag . NewFlagSet ( \"config\" , flag . ContinueOnError )
	f . Usage = func () {
		fmt . Println ( f . FlagUsages ())
		os . Exit ( 0 )
	}
	// Path to one or more config files to load into koanf along with some config params.
	f . StringSlice ( \"conf\" , [] string { \"mock/mock.toml\" }, \"path to one or more .toml config files\" )
	f . String ( \"time\" , \"2020-01-01\" , \"a time string\" )
	f . String ( \"type\" , \"xxx\" , \"type of the app\" )
	f . Parse ( os . Args [ 1 :])

	// Load the config files provided in the commandline.
	cFiles , _ := f . GetStringSlice ( \"conf\" )
	for _ , c := range cFiles {
		if err := k . Load ( file . Provider ( c ), toml . Parser ()); err != nil {
			log . Fatalf ( \"error loading file: %v\" , err )
		}
	}

	// \"time\" and \"type\" may have been loaded from the config file, but
	// they can still be overridden with the values from the command line.
	// The bundled posflag.Provider takes a flagset from the spf13/pflag lib.
	// Passing the koanf instance to posflag helps it deal with default command
	// line flag values that are not present in conf maps from previously loaded
	// providers.
	if err := k . Load ( posflag . Provider ( f , \".\" , k ), nil ); err != nil {
		log . Fatalf ( \"error loading config: %v\" , err )
	}

	fmt . Println ( \"time is = \" , k . String ( \"time\" ))
}

阅读环境变量

koanf/v2\”
\”github.com/knadh/ koanf /parsers/json\”
\”github.com/knadh/ koanf /providers/env/v2\”
\”github.com/knadh/ koanf /providers/file\”
)

// Global koanf instance. Use . as the key path delimiter. This can be / or anything.
var k = koanf .New(\”.\”)

func main() {
// Load JSON config.
if err := k.Load(file.Provider(\”mock/mock.json\”), json.Parser()); err != nil {
log.Fatalf(\”error loading config: %v\”, err)
}

// Load only environment variables with prefix \”MYVAR_\” and merge into config.
// Transform var names by:
// 1. Converting to lowercase
// 2. Removing \”MYVAR_\” prefix
// 3. Replacing \”_\” with \”.\” to representing nesting using the . delimiter.
// Example: MYVAR_PARENT1_CHILD1_NAME becomes \”parent1.child1.name\”
k.Load(env.Provider(\”.\”, env.Opt{
Prefix: \”MYVAR_\”,
TransformFunc: func(k, v string) (string, any) {
// Transform the key.
k = strings.ReplaceAll(strings.ToLower(strings.TrimPrefix(k, \”MYVAR_\”)), \”_\”, \”.\”)

// Transform the value into slices, if they contain spaces.
// Eg: MYVAR_TAGS=\”foo bar baz\” -> tags: [\”foo\”, \”bar\”, \”baz\”]
// This is to demonstrate that string values can be transformed to any type
// where necessary.
if strings.Contains(v, \” \”) {
return k, strings.Split(v, \” \”)
}

return k, v
},
}), nil)

fmt.Println(\”name is =\”, k.String(\”parent1.child1.name\”))
fmt.Println(\”time is =\”, k.Time(\”time\”, time.DateOnly))
fmt.Println(\”ids are =\”, k.Strings(\”parent1.child1.grandchild1.ids\”))
}“`

### Reading from an S3 bucket

“`go
// Load JSON config from s3.
if err := k.Load(s3.Provider(s3.Config{
AccessKey: os.Getenv(\”AWS_S3_ACCESS_KEY\”),
SecretKey: os.Getenv(\”AWS_S3_SECRET_KEY\”),
Region: os.Getenv(\”AWS_S3_REGION\”),
Bucket: os.Getenv(\”AWS_S3_BUCKET\”),
ObjectKey: \”dir/config.json\”,
}), json.Parser()); err != nil {
log.Fatalf(\”error loading config: %v\”, err)
}\”>

 package main

import (
	\"fmt\"
	\"log\"
	\"strings\"

	\"github.com/knadh/ koanf /v2\"
	\"github.com/knadh/ koanf /parsers/json\"
	\"github.com/knadh/ koanf /providers/env/v2\"
	\"github.com/knadh/ koanf /providers/file\"
)

// Global koanf instance. Use . as the key path delimiter. This can be / or anything.
var k = koanf . New ( \".\" )

func main () {
	// Load JSON config.
	if err := k . Load ( file . Provider ( \"mock/mock.json\" ), json . Parser ()); err != nil {
		log . Fatalf ( \"error loading config: %v\" , err )
	}

	// Load only environment variables with prefix \"MYVAR_\" and merge into config.
	// Transform var names by:
	// 1. Converting to lowercase
	// 2. Removing \"MYVAR_\" prefix  
	// 3. Replacing \"_\" with \".\" to representing nesting using the . delimiter.
	// Example: MYVAR_PARENT1_CHILD1_NAME becomes \"parent1.child1.name\"
	k . Load ( env . Provider ( \".\" , env. Opt {
		Prefix : \"MYVAR_\" ,
		TransformFunc : func ( k , v string ) ( string , any ) {
			// Transform the key.
			k = strings . ReplaceAll ( strings . ToLower ( strings . TrimPrefix ( k , \"MYVAR_\" )), \"_\" , \".\" )

			// Transform the value into slices, if they contain spaces.
			// Eg: MYVAR_TAGS=\"foo bar baz\" -> tags: [\"foo\", \"bar\", \"baz\"]
			// This is to demonstrate that string values can be transformed to any type
			// where necessary.
			if strings . Contains ( v , \" \" ) {
				return k , strings . Split ( v , \" \" )
			}

			return k , v
		},
	}), nil )

	fmt . Println ( \"name is =\" , k . String ( \"parent1.child1.name\" ))
	fmt . Println ( \"time is =\" , k . Time ( \"time\" , time . DateOnly ))
	fmt . Println ( \"ids are =\" , k . Strings ( \"parent1.child1.grandchild1.ids\" ))
} `` `


### Reading from an S3 bucket

` `` go
// Load JSON config from s3.
if err := k . Load ( s3 . Provider (s3. Config {
	AccessKey : os . Getenv ( \"AWS_S3_ACCESS_KEY\" ),
	SecretKey : os . Getenv ( \"AWS_S3_SECRET_KEY\" ),
	Region :    os . Getenv ( \"AWS_S3_REGION\" ),
	Bucket :    os . Getenv ( \"AWS_S3_BUCKET\" ),
	ObjectKey : \"dir/config.json\" ,
}), json . Parser ()); err != nil {
	log . Fatalf ( \"error loading config: %v\" , err )
}

读取原始字节

捆绑的rawbytes提供商可用于从源中读取任意字节,例如数据库或HTTP调用。

koanf/v2\”
\”github.com/knadh/ koanf /parsers/json\”
\”github.com/knadh/ koanf /providers/rawbytes\”
)

// Global koanf instance. Use . as the key path delimiter. This can be / or anything.
var k = koanf .New(\”.\”)

func main() {
b := []byte(`{\”type\”: \”rawbytes\”, \”parent1\”: {\”child1\”: {\”type\”: \”rawbytes\”}}}`)
k.Load(rawbytes.Provider(b), json.Parser())
fmt.Println(\”type is = \”, k.String(\”parent1.child1.type\”))
}\”>

 package main

import (
	\"fmt\"

	\"github.com/knadh/ koanf /v2\"
	\"github.com/knadh/ koanf /parsers/json\"
	\"github.com/knadh/ koanf /providers/rawbytes\"
)

// Global koanf instance. Use . as the key path delimiter. This can be / or anything.
var k = koanf . New ( \".\" )

func main () {
	b := [] byte ( `{\"type\": \"rawbytes\", \"parent1\": {\"child1\": {\"type\": \"rawbytes\"}}}` )
	k . Load ( rawbytes . Provider ( b ), json . Parser ())
	fmt . Println ( \"type is = \" , k . String ( \"parent1.child1.type\" ))
}

解除和编组

Parser可用于根据字段标签将koanf实例中的值和扫描值扫描到一个结构中,并将koanf实例元用回到序列化字节中,例如json或yaml文件

koanf/v2\”
\”github.com/knadh/ koanf /parsers/json\”
\”github.com/knadh/ koanf /providers/file\”
)

// Global koanf instance. Use . as the key path delimiter. This can be / or anything.
var (
k = koanf .New(\”.\”)
parser = json.Parser()
)

func main() {
// Load JSON config.
if err := k.Load(file.Provider(\”mock/mock.json\”), parser); err != nil {
log.Fatalf(\”error loading config: %v\”, err)
}

// Structure to unmarshal nested conf to.
type childStruct struct {
Name string ` koanf :\”name\”`
Type string ` koanf :\”type\”`
Empty map[string]string ` koanf :\”empty\”`
GrandChild struct {
Ids []int ` koanf :\”ids\”`
On bool ` koanf :\”on\”`
} ` koanf :\”grandchild1\”`
}

var out childStruct

// Quick unmarshal.
k.Unmarshal(\”parent1.child1\”, &out)
fmt.Println(out)

// Unmarshal with advanced config.
out = childStruct{}
k.UnmarshalWithConf(\”parent1.child1\”, &out, koanf .UnmarshalConf{Tag: \” koanf \”})
fmt.Println(out)

// Marshal the instance back to JSON.
// The parser instance can be anything, eg: json.Parser(), yaml.Parser() etc.
b, _ := k.Marshal(parser)
fmt.Println(string(b))
}\”>

 package main

import (
	\"fmt\"
	\"log\"

	\"github.com/knadh/ koanf /v2\"
	\"github.com/knadh/ koanf /parsers/json\"
	\"github.com/knadh/ koanf /providers/file\"
)

// Global koanf instance. Use . as the key path delimiter. This can be / or anything.
var (
	k      = koanf . New ( \".\" )
	parser = json . Parser ()
)

func main () {
	// Load JSON config.
	if err := k . Load ( file . Provider ( \"mock/mock.json\" ), parser ); err != nil {
		log . Fatalf ( \"error loading config: %v\" , err )
	}

	// Structure to unmarshal nested conf to.
	type childStruct struct {
		Name       string            ` koanf :\"name\"`
		Type       string            ` koanf :\"type\"`
		Empty      map [ string ] string ` koanf :\"empty\"`
		GrandChild struct {
			Ids [] int ` koanf :\"ids\"`
			On  bool  ` koanf :\"on\"`
		} ` koanf :\"grandchild1\"`
	}

	var out childStruct

	// Quick unmarshal.
	k . Unmarshal ( \"parent1.child1\" , & out )
	fmt . Println ( out )

	// Unmarshal with advanced config.
	out = childStruct {}
	k . UnmarshalWithConf ( \"parent1.child1\" , & out , koanf . UnmarshalConf { Tag : \" koanf \" })
	fmt . Println ( out )

	// Marshal the instance back to JSON.
	// The parser instance can be anything, eg: json.Parser(), yaml.Parser() etc.
	b , _ := k . Marshal ( parser )
	fmt . Println ( string ( b ))
}

用平坦的路径拆开

有时,有必要将各种钥匙从各种嵌套结构转换为平坦的目标结构。 UnmarshalConf.FlatPaths标志是可能的。

koanf/v2\”
\”github.com/knadh/ koanf /parsers/json\”
\”github.com/knadh/ koanf /providers/file\”
)

// Global koanf instance. Use . as the key path delimiter. This can be / or anything.
var k = koanf .New(\”.\”)

func main() {
// Load JSON config.
if err := k.Load(file.Provider(\”mock/mock.json\”), json.Parser()); err != nil {
log.Fatalf(\”error loading config: %v\”, err)
}

type rootFlat struct {
Type string ` koanf :\”type\”`
Empty map[string]string ` koanf :\”empty\”`
Parent1Name string ` koanf :\”parent1.name\”`
Parent1ID int ` koanf :\”parent1.id\”`
Parent1Child1Name string ` koanf :\”parent1.child1.name\”`
Parent1Child1Type string ` koanf :\”parent1.child1.type\”`
Parent1Child1Empty map[string]string ` koanf :\”parent1.child1.empty\”`
Parent1Child1Grandchild1IDs []int ` koanf :\”parent1.child1.grandchild1.ids\”`
Parent1Child1Grandchild1On bool ` koanf :\”parent1.child1.grandchild1.on\”`
}

// Unmarshal the whole root with FlatPaths: True.
var o1 rootFlat
k.UnmarshalWithConf(\”\”, &o1, koanf .UnmarshalConf{Tag: \” koanf \”, FlatPaths: true})
fmt.Println(o1)

// Unmarshal a child structure of \”parent1\”.
type subFlat struct {
Name string ` koanf :\”name\”`
ID int ` koanf :\”id\”`
Child1Name string ` koanf :\”child1.name\”`
Child1Type string ` koanf :\”child1.type\”`
Child1Empty map[string]string ` koanf :\”child1.empty\”`
Child1Grandchild1IDs []int ` koanf :\”child1.grandchild1.ids\”`
Child1Grandchild1On bool ` koanf :\”child1.grandchild1.on\”`
}

var o2 subFlat
k.UnmarshalWithConf(\”parent1\”, &o2, koanf .UnmarshalConf{Tag: \” koanf \”, FlatPaths: true})
fmt.Println(o2)
}\”>

 package main

import (
	\"fmt\"
	\"log\"

	\"github.com/knadh/ koanf /v2\"
	\"github.com/knadh/ koanf /parsers/json\"
	\"github.com/knadh/ koanf /providers/file\"
)

// Global koanf instance. Use . as the key path delimiter. This can be / or anything.
var k = koanf . New ( \".\" )

func main () {
	// Load JSON config.
	if err := k . Load ( file . Provider ( \"mock/mock.json\" ), json . Parser ()); err != nil {
		log . Fatalf ( \"error loading config: %v\" , err )
	}

	type rootFlat struct {
		Type                        string            ` koanf :\"type\"`
		Empty                       map [ string ] string ` koanf :\"empty\"`
		Parent1Name                 string            ` koanf :\"parent1.name\"`
		Parent1ID                   int               ` koanf :\"parent1.id\"`
		Parent1Child1Name           string            ` koanf :\"parent1.child1.name\"`
		Parent1Child1Type           string            ` koanf :\"parent1.child1.type\"`
		Parent1Child1Empty          map [ string ] string ` koanf :\"parent1.child1.empty\"`
		Parent1Child1Grandchild1IDs [] int             ` koanf :\"parent1.child1.grandchild1.ids\"`
		Parent1Child1Grandchild1On  bool              ` koanf :\"parent1.child1.grandchild1.on\"`
	}

	// Unmarshal the whole root with FlatPaths: True.
	var o1 rootFlat
	k . UnmarshalWithConf ( \"\" , & o1 , koanf . UnmarshalConf { Tag : \" koanf \" , FlatPaths : true })
	fmt . Println ( o1 )

	// Unmarshal a child structure of \"parent1\".
	type subFlat struct {
		Name                 string            ` koanf :\"name\"`
		ID                   int               ` koanf :\"id\"`
		Child1Name           string            ` koanf :\"child1.name\"`
		Child1Type           string            ` koanf :\"child1.type\"`
		Child1Empty          map [ string ] string ` koanf :\"child1.empty\"`
		Child1Grandchild1IDs [] int             ` koanf :\"child1.grandchild1.ids\"`
		Child1Grandchild1On  bool              ` koanf :\"child1.grandchild1.on\"`
	}

	var o2 subFlat
	k . UnmarshalWithConf ( \"parent1\" , & o2 , koanf . UnmarshalConf { Tag : \" koanf \" , FlatPaths : true })
	fmt . Println ( o2 )
}

从嵌套地图上读取

捆绑的confmap提供商采用可以加载到koanf实例中的map[string]interface{}

koanf/v2\”
\”github.com/knadh/ koanf /providers/confmap\”
\”github.com/knadh/ koanf /providers/file\”
\”github.com/knadh/ koanf /parsers/json\”
\”github.com/knadh/ koanf /parsers/yaml\”
)

// Global koanf instance. Use \”.\” as the key path delimiter. This can be \”/\” or any character.
var k = koanf .New(\”.\”)

func main() {
// Load default values using the confmap provider.
// We provide a flat map with the \”.\” delimiter.
// A nested map can be loaded by setting the delimiter to an empty string \”\”.
k.Load(confmap.Provider(map[string]interface{}{
\”parent1.name\”: \”Default Name\”,
\”parent3.name\”: \”New name here\”,
}, \”.\”), nil)

// Load JSON config on top of the default values.
if err := k.Load(file.Provider(\”mock/mock.json\”), json.Parser()); err != nil {
log.Fatalf(\”error loading config: %v\”, err)
}

// Load YAML config and merge into the previously loaded config (because we can).
k.Load(file.Provider(\”mock/mock.yml\”), yaml.Parser())

fmt.Println(\”parent\’s name is = \”, k.String(\”parent1.name\”))
fmt.Println(\”parent\’s ID is = \”, k.Int(\”parent1.id\”))
}\”>

 package main

import (
	\"fmt\"
	\"log\"

	\"github.com/knadh/ koanf /v2\"
	\"github.com/knadh/ koanf /providers/confmap\"
	\"github.com/knadh/ koanf /providers/file\"
	\"github.com/knadh/ koanf /parsers/json\"
	\"github.com/knadh/ koanf /parsers/yaml\"
)

// Global koanf instance. Use \".\" as the key path delimiter. This can be \"/\" or any character.
var k = koanf . New ( \".\" )

func main () {
	// Load default values using the confmap provider.
	// We provide a flat map with the \".\" delimiter.
	// A nested map can be loaded by setting the delimiter to an empty string \"\".
	k . Load ( confmap . Provider ( map [ string ] interface {}{
		\"parent1.name\" : \"Default Name\" ,
		\"parent3.name\" : \"New name here\" ,
	}, \".\" ), nil )

	// Load JSON config on top of the default values.
	if err := k . Load ( file . Provider ( \"mock/mock.json\" ), json . Parser ()); err != nil {
		log . Fatalf ( \"error loading config: %v\" , err )
	}

	// Load YAML config and merge into the previously loaded config (because we can).
	k . Load ( file . Provider ( \"mock/mock.yml\" ), yaml . Parser ())

	fmt . Println ( \"parent\'s name is = \" , k . String ( \"parent1.name\" ))
	fmt . Println ( \"parent\'s ID is = \" , k . Int ( \"parent1.id\" ))
}

从结构阅读

捆绑的structs提供商可用于读取从结构的数据,以加载到koanf实例中。

koanf/v2\”
\”github.com/knadh/ koanf /providers/structs\”
)

// Global koanf instance. Use \”.\” as the key path delimiter. This can be \”/\” or any character.
var k = koanf .New(\”.\”)

type parentStruct struct {
Name string ` koanf :\”name\”`
ID int ` koanf :\”id\”`
Child1 childStruct ` koanf :\”child1\”`
}
type childStruct struct {
Name string ` koanf :\”name\”`
Type string ` koanf :\”type\”`
Empty map[string]string ` koanf :\”empty\”`
Grandchild1 grandchildStruct ` koanf :\”grandchild1\”`
}
type grandchildStruct struct {
Ids []int ` koanf :\”ids\”`
On bool ` koanf :\”on\”`
}
type sampleStruct struct {
Type string ` koanf :\”type\”`
Empty map[string]string ` koanf :\”empty\”`
Parent1 parentStruct ` koanf :\”parent1\”`
}

func main() {
// Load default values using the structs provider.
// We provide a struct along with the struct tag ` koanf ` to the
// provider.
k.Load(structs.Provider(sampleStruct{
Type: \”json\”,
Empty: make(map[string]string),
Parent1: parentStruct{
Name: \”parent1\”,
ID: 1234,
Child1: childStruct{
Name: \”child1\”,
Type: \”json\”,
Empty: make(map[string]string),
Grandchild1: grandchildStruct{
Ids: []int{1, 2, 3},
On: true,
},
},
},
}, \” koanf \”), nil)

fmt.Printf(\”name is = `%s`\\n\”, k.String(\”parent1.child1.name\”))
}\”>

 package main

import (
	\"fmt\"

	\"github.com/knadh/ koanf /v2\"
	\"github.com/knadh/ koanf /providers/structs\"
)

// Global koanf instance. Use \".\" as the key path delimiter. This can be \"/\" or any character.
var k = koanf . New ( \".\" )

type parentStruct struct {
	Name   string      ` koanf :\"name\"`
	ID     int         ` koanf :\"id\"`
	Child1 childStruct ` koanf :\"child1\"`
}
type childStruct struct {
	Name        string            ` koanf :\"name\"`
	Type        string            ` koanf :\"type\"`
	Empty       map [ string ] string ` koanf :\"empty\"`
	Grandchild1 grandchildStruct  ` koanf :\"grandchild1\"`
}
type grandchildStruct struct {
	Ids [] int ` koanf :\"ids\"`
	On  bool  ` koanf :\"on\"`
}
type sampleStruct struct {
	Type    string            ` koanf :\"type\"`
	Empty   map [ string ] string ` koanf :\"empty\"`
	Parent1 parentStruct      ` koanf :\"parent1\"`
}

func main () {
	// Load default values using the structs provider.
	// We provide a struct along with the struct tag ` koanf ` to the
	// provider.
	k . Load ( structs . Provider ( sampleStruct {
		Type :  \"json\" ,
		Empty : make ( map [ string ] string ),
		Parent1 : parentStruct {
			Name : \"parent1\" ,
			ID :   1234 ,
			Child1 : childStruct {
				Name :  \"child1\" ,
				Type :  \"json\" ,
				Empty : make ( map [ string ] string ),
				Grandchild1 : grandchildStruct {
					Ids : [] int { 1 , 2 , 3 },
					On :  true ,
				},
			},
		},
	}, \" koanf \" ), nil )

	fmt . Printf ( \"name is = `%s` \\n \" , k . String ( \"parent1.child1.name\" ))
}

合并行为

默认行为

当您以这种方式创建koanf时,默认行为是: koanf .New(delim) ,最新的加载配置将与上一个合并。

例如: first.yml

 key : [1,2,3]

second.yml

 key : \' string \'

加载second.yml时,它将覆盖first.yml类型。

如果不需要此行为,则可以“严格”合并。在同一情况下, Load将返回错误。

koanf/v2\”
\”github.com/knadh/ koanf /maps\”
\”github.com/knadh/ koanf /parsers/json\”
\”github.com/knadh/ koanf /parsers/yaml\”
\”github.com/knadh/ koanf /providers/file\”
)

var conf = koanf .Conf{
Delim: \”.\”,
StrictMerge: true,
}
var k = koanf .NewWithConf(conf)

func main() {
yamlPath := \”mock/mock.yml\”
if err := k.Load(file.Provider(yamlPath), yaml.Parser()); err != nil {
log.Fatalf(\”error loading config: %v\”, err)
}

jsonPath := \”mock/mock.json\”
if err := k.Load(file.Provider(jsonPath), json.Parser()); err != nil {
log.Fatalf(\”error loading config: %v\”, err)
}
}\”>

 package main

import (
	\"errors\"
	\"log\"

	\"github.com/knadh/ koanf /v2\"
	\"github.com/knadh/ koanf /maps\"
	\"github.com/knadh/ koanf /parsers/json\"
	\"github.com/knadh/ koanf /parsers/yaml\"
	\"github.com/knadh/ koanf /providers/file\"
)

var conf = koanf . Conf {
	Delim :       \".\" ,
	StrictMerge : true ,
}
var k = koanf . NewWithConf ( conf )

func main () {
	yamlPath := \"mock/mock.yml\"
	if err := k . Load ( file . Provider ( yamlPath ), yaml . Parser ()); err != nil {
		log . Fatalf ( \"error loading config: %v\" , err )
	}

	jsonPath := \"mock/mock.json\"
	if err := k . Load ( file . Provider ( jsonPath ), json . Parser ()); err != nil {
		log . Fatalf ( \"error loading config: %v\" , err )
	}
}

注意:当合并不同的扩展名时,每个解析器都可以对其类型的处理方式有所不同,这意味着即使您的负载相同类型,也可能会在StrictMerge: true

例如:合并JSON和YAML很可能会失败,因为JSON将整数视为Float64,而Yaml将其视为整数。

合并和关键案例灵敏度的顺序

  • config键在koanf中对大小写。例如, app.server.portAPP.SERVER.port不一样。
  • koanf不会在来自各个提供商的加载配置上施加任何订购。每个连续的Load()Merge()将新的配置合并到现有配置中。也就是说,可以先加载环境变量,然后在其顶部加载文件,然后在其顶部或任何此类订单上加载命令行变量。

定制提供商和解析器

提供商返回一个可以直接加载到koanf koanf .Load()中的嵌套map[string]interface{}配置,或者它可以返回可以用解析器解析的原始字节(再次使用koanf .Load()加载。

定制合并策略

默认情况下,当使用Load()合并两个配置源时, koanf递归合并了嵌套地图( map[string]interface{} )的键,而静态值则被覆盖(切片,字符串等)。可以通过使用WithMergeFunc选项提供自定义合并函数来更改此行为。

koanf/v2\”
\”github.com/knadh/ koanf /maps\”
\”github.com/knadh/ koanf /parsers/json\”
\”github.com/knadh/ koanf /parsers/yaml\”
\”github.com/knadh/ koanf /providers/file\”
)

var conf = koanf .Conf{
Delim: \”.\”,
S

下载源码

通过命令行克隆项目:

git clone https://github.com/knadh/koanf.git

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 koanf https://www.zuozi.net/34268.html

dtm
上一篇: dtm
Dependencies
下一篇: Dependencies
常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务