ini

package module
v1.33.0 Latest Latest
Warning

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

Go to latest
Published: Mar 8, 2018 License: Apache-2.0 Imports: 15 Imported by: 0

README

INI Build Status Sourcegraph

Package ini provides INI file read and write functionality in Go.

简体中文

Feature

  • Load multiple data sources([]byte, file and io.ReadCloser) with overwrites.
  • Read with recursion values.
  • Read with parent-child sections.
  • Read with auto-increment key names.
  • Read with multiple-line values.
  • Read with tons of helper methods.
  • Read and convert values to Go types.
  • Read and WRITE comments of sections and keys.
  • Manipulate sections, keys and comments with ease.
  • Keep sections and keys in order as you parse and save.

Installation

To use a tagged revision:

go get gopkg.in/ini.v1

To use with latest changes:

go get github.com/go-ini/ini

Please add -u flag to update in the future.

Testing

If you want to test on your machine, please apply -t flag:

go get -t gopkg.in/ini.v1

Please add -u flag to update in the future.

Getting Started

Loading from data sources

A Data Source is either raw data in type []byte, a file name with type string or io.ReadCloser. You can load as many data sources as you want. Passing other types will simply return an error.

cfg, err := ini.Load([]byte("raw data"), "filename", ioutil.NopCloser(bytes.NewReader([]byte("some other data"))))

Or start with an empty object:

cfg := ini.Empty()

When you cannot decide how many data sources to load at the beginning, you will still be able to Append() them later.

err := cfg.Append("other file", []byte("other raw data"))

If you have a list of files with possibilities that some of them may not available at the time, and you don't know exactly which ones, you can use LooseLoad to ignore nonexistent files without returning error.

cfg, err := ini.LooseLoad("filename", "filename_404")

The cool thing is, whenever the file is available to load while you're calling Reload method, it will be counted as usual.

Ignore cases of key name

When you do not care about cases of section and key names, you can use InsensitiveLoad to force all names to be lowercased while parsing.

cfg, err := ini.InsensitiveLoad("filename")
//...

// sec1 and sec2 are the exactly same section object
sec1, err := cfg.GetSection("Section")
sec2, err := cfg.GetSection("SecTIOn")

// key1 and key2 are the exactly same key object
key1, err := sec1.GetKey("Key")
key2, err := sec2.GetKey("KeY")
MySQL-like boolean key

MySQL's configuration allows a key without value as follows:

[mysqld]
...
skip-host-cache
skip-name-resolve

By default, this is considered as missing value. But if you know you're going to deal with those cases, you can assign advanced load options:

cfg, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true}, "my.cnf"))

The value of those keys are always true, and when you save to a file, it will keep in the same foramt as you read.

To generate such keys in your program, you could use NewBooleanKey:

key, err := sec.NewBooleanKey("skip-host-cache")
Comment

Take care that following format will be treated as comment:

  1. Line begins with # or ;
  2. Words after # or ;
  3. Words after section name (i.e words after [some section name])

If you want to save a value with # or ;, please quote them with ` or """.

Alternatively, you can use following LoadOptions to completely ignore inline comments:

cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, "app.ini"))
Working with sections

To get a section, you would need to:

section, err := cfg.GetSection("section name")

For a shortcut for default section, just give an empty string as name:

section, err := cfg.GetSection("")

When you're pretty sure the section exists, following code could make your life easier:

section := cfg.Section("section name")

What happens when the section somehow does not exist? Don't panic, it automatically creates and returns a new section to you.

To create a new section:

err := cfg.NewSection("new section")

To get a list of sections or section names:

sections := cfg.Sections()
names := cfg.SectionStrings()
Working with keys

To get a key under a section:

key, err := cfg.Section("").GetKey("key name")

Same rule applies to key operations:

key := cfg.Section("").Key("key name")

To check if a key exists:

yes := cfg.Section("").HasKey("key name")

To create a new key:

err := cfg.Section("").NewKey("name", "value")

To get a list of keys or key names:

keys := cfg.Section("").Keys()
names := cfg.Section("").KeyStrings()

To get a clone hash of keys and corresponding values:

hash := cfg.Section("").KeysHash()
Working with values

To get a string value:

val := cfg.Section("").Key("key name").String()

To validate key value on the fly:

val := cfg.Section("").Key("key name").Validate(func(in string) string {
	if len(in) == 0 {
		return "default"
	}
	return in
})

If you do not want any auto-transformation (such as recursive read) for the values, you can get raw value directly (this way you get much better performance):

val := cfg.Section("").Key("key name").Value()

To check if raw value exists:

yes := cfg.Section("").HasValue("test value")

To get value with types:

// For boolean values:
// true when value is: 1, t, T, TRUE, true, True, YES, yes, Yes, y, ON, on, On
// false when value is: 0, f, F, FALSE, false, False, NO, no, No, n, OFF, off, Off
v, err = cfg.Section("").Key("BOOL").Bool()
v, err = cfg.Section("").Key("FLOAT64").Float64()
v, err = cfg.Section("").Key("INT").Int()
v, err = cfg.Section("").Key("INT64").Int64()
v, err = cfg.Section("").Key("UINT").Uint()
v, err = cfg.Section("").Key("UINT64").Uint64()
v, err = cfg.Section("").Key("TIME").TimeFormat(time.RFC3339)
v, err = cfg.Section("").Key("TIME").Time() // RFC3339

v = cfg.Section("").Key("BOOL").MustBool()
v = cfg.Section("").Key("FLOAT64").MustFloat64()
v = cfg.Section("").Key("INT").MustInt()
v = cfg.Section("").Key("INT64").MustInt64()
v = cfg.Section("").Key("UINT").MustUint()
v = cfg.Section("").Key("UINT64").MustUint64()
v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339)
v = cfg.Section("").Key("TIME").MustTime() // RFC3339

// Methods start with Must also accept one argument for default value
// when key not found or fail to parse value to given type.
// Except method MustString, which you have to pass a default value.

v = cfg.Section("").Key("String").MustString("default")
v = cfg.Section("").Key("BOOL").MustBool(true)
v = cfg.Section("").Key("FLOAT64").MustFloat64(1.25)
v = cfg.Section("").Key("INT").MustInt(10)
v = cfg.Section("").Key("INT64").MustInt64(99)
v = cfg.Section("").Key("UINT").MustUint(3)
v = cfg.Section("").Key("UINT64").MustUint64(6)
v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339, time.Now())
v = cfg.Section("").Key("TIME").MustTime(time.Now()) // RFC3339

What if my value is three-line long?

[advance]
ADDRESS = """404 road,
NotFound, State, 5000
Earth"""

Not a problem!

cfg.Section("advance").Key("ADDRESS").String()

/* --- start ---
404 road,
NotFound, State, 5000
Earth
------  end  --- */

That's cool, how about continuation lines?

[advance]
two_lines = how about \
	continuation lines?
lots_of_lines = 1 \
	2 \
	3 \
	4

Piece of cake!

cfg.Section("advance").Key("two_lines").String() // how about continuation lines?
cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4

Well, I hate continuation lines, how do I disable that?

cfg, err := ini.LoadSources(ini.LoadOptions{
	IgnoreContinuation: true,
}, "filename")

Holy crap!

Note that single quotes around values will be stripped:

foo = "some value" // foo: some value
bar = 'some value' // bar: some value

Sometimes you downloaded file from Crowdin has values like the following (value is surrounded by double quotes and quotes in the value are escaped):

create_repo="created repository <a href=\"%s\">%s</a>"

How do you transform this to regular format automatically?

cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
cfg.Section("<name of your section>").Key("create_repo").String()
// You got: created repository <a href="%s">%s</a>

That's all? Hmm, no.

Helper methods of working with values

To get value with given candidates:

v = cfg.Section("").Key("STRING").In("default", []string{"str", "arr", "types"})
v = cfg.Section("").Key("FLOAT64").InFloat64(1.1, []float64{1.25, 2.5, 3.75})
v = cfg.Section("").Key("INT").InInt(5, []int{10, 20, 30})
v = cfg.Section("").Key("INT64").InInt64(10, []int64{10, 20, 30})
v = cfg.Section("").Key("UINT").InUint(4, []int{3, 6, 9})
v = cfg.Section("").Key("UINT64").InUint64(8, []int64{3, 6, 9})
v = cfg.Section("").Key("TIME").InTimeFormat(time.RFC3339, time.Now(), []time.Time{time1, time2, time3})
v = cfg.Section("").Key("TIME").InTime(time.Now(), []time.Time{time1, time2, time3}) // RFC3339

Default value will be presented if value of key is not in candidates you given, and default value does not need be one of candidates.

To validate value in a given range:

vals = cfg.Section("").Key("FLOAT64").RangeFloat64(0.0, 1.1, 2.2)
vals = cfg.Section("").Key("INT").RangeInt(0, 10, 20)
vals = cfg.Section("").Key("INT64").RangeInt64(0, 10, 20)
vals = cfg.Section("").Key("UINT").RangeUint(0, 3, 9)
vals = cfg.Section("").Key("UINT64").RangeUint64(0, 3, 9)
vals = cfg.Section("").Key("TIME").RangeTimeFormat(time.RFC3339, time.Now(), minTime, maxTime)
vals = cfg.Section("").Key("TIME").RangeTime(time.Now(), minTime, maxTime) // RFC3339
Auto-split values into a slice

To use zero value of type for invalid inputs:

// Input: 1.1, 2.2, 3.3, 4.4 -> [1.1 2.2 3.3 4.4]
// Input: how, 2.2, are, you -> [0.0 2.2 0.0 0.0]
vals = cfg.Section("").Key("STRINGS").Strings(",")
vals = cfg.Section("").Key("FLOAT64S").Float64s(",")
vals = cfg.Section("").Key("INTS").Ints(",")
vals = cfg.Section("").Key("INT64S").Int64s(",")
vals = cfg.Section("").Key("UINTS").Uints(",")
vals = cfg.Section("").Key("UINT64S").Uint64s(",")
vals = cfg.Section("").Key("TIMES").Times(",")

To exclude invalid values out of result slice:

// Input: 1.1, 2.2, 3.3, 4.4 -> [1.1 2.2 3.3 4.4]
// Input: how, 2.2, are, you -> [2.2]
vals = cfg.Section("").Key("FLOAT64S").ValidFloat64s(",")
vals = cfg.Section("").Key("INTS").ValidInts(",")
vals = cfg.Section("").Key("INT64S").ValidInt64s(",")
vals = cfg.Section("").Key("UINTS").ValidUints(",")
vals = cfg.Section("").Key("UINT64S").ValidUint64s(",")
vals = cfg.Section("").Key("TIMES").ValidTimes(",")

Or to return nothing but error when have invalid inputs:

// Input: 1.1, 2.2, 3.3, 4.4 -> [1.1 2.2 3.3 4.4]
// Input: how, 2.2, are, you -> error
vals = cfg.Section("").Key("FLOAT64S").StrictFloat64s(",")
vals = cfg.Section("").Key("INTS").StrictInts(",")
vals = cfg.Section("").Key("INT64S").StrictInt64s(",")
vals = cfg.Section("").Key("UINTS").StrictUints(",")
vals = cfg.Section("").Key("UINT64S").StrictUint64s(",")
vals = cfg.Section("").Key("TIMES").StrictTimes(",")
Save your configuration

Finally, it's time to save your configuration to somewhere.

A typical way to save configuration is writing it to a file:

// ...
err = cfg.SaveTo("my.ini")
err = cfg.SaveToIndent("my.ini", "\t")

Another way to save is writing to a io.Writer interface:

// ...
cfg.WriteTo(writer)
cfg.WriteToIndent(writer, "\t")

By default, spaces are used to align "=" sign between key and values, to disable that:

ini.PrettyFormat = false

Advanced Usage

Recursive Values

For all value of keys, there is a special syntax %(<name>)s, where <name> is the key name in same section or default section, and %(<name>)s will be replaced by corresponding value(empty string if key not found). You can use this syntax at most 99 level of recursions.

NAME = ini

[author]
NAME = Unknwon
GITHUB = https://github.com/%(NAME)s

[package]
FULL_NAME = github.com/go-ini/%(NAME)s
cfg.Section("author").Key("GITHUB").String()		// https://github.com/Unknwon
cfg.Section("package").Key("FULL_NAME").String()	// github.com/go-ini/ini
Parent-child Sections

You can use . in section name to indicate parent-child relationship between two or more sections. If the key not found in the child section, library will try again on its parent section until there is no parent section.

NAME = ini
VERSION = v1
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s

[package]
CLONE_URL = https://%(IMPORT_PATH)s

[package.sub]
cfg.Section("package.sub").Key("CLONE_URL").String()	// https://gopkg.in/ini.v1
Retrieve parent keys available to a child section
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
Same Key with Multiple Values

Do you ever have a configuration file like this?

[remote "origin"]
url = https://github.com/Antergone/test1.git
url = https://github.com/Antergone/test2.git
fetch = +refs/heads/*:refs/remotes/origin/*

By default, only the last read value will be kept for the key url. If you want to keep all copies of value of this key, you can use ShadowLoad to achieve it:

cfg, err := ini.ShadowLoad(".gitconfig")
// ...

f.Section(`remote "origin"`).Key("url").String() 
// Result: https://github.com/Antergone/test1.git

f.Section(`remote "origin"`).Key("url").ValueWithShadows()
// Result:  []string{
//              "https://github.com/Antergone/test1.git",
//              "https://github.com/Antergone/test2.git",
//          }
Unparseable Sections

Sometimes, you have sections that do not contain key-value pairs but raw content, to handle such case, you can use LoadOptions.UnparsableSections:

cfg, err := ini.LoadSources(ini.LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))

body := cfg.Section("COMMENTS").Body()

/* --- start ---
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
------  end  --- */
Auto-increment Key Names

If key name is - in data source, then it would be seen as special syntax for auto-increment key name start from 1, and every section is independent on counter.

[features]
-: Support read/write comments of keys and sections
-: Support auto-increment of key names
-: Support load multiple files to overwrite key values
cfg.Section("features").KeyStrings()	// []{"#1", "#2", "#3"}
Map To Struct

Want more objective way to play with INI? Cool.

Name = Unknwon
age = 21
Male = true
Born = 1993-01-01T20:17:05Z

[Note]
Content = Hi is a good man!
Cities = HangZhou, Boston
type Note struct {
	Content string
	Cities  []string
}

type Person struct {
	Name string
	Age  int `ini:"age"`
	Male bool
	Born time.Time
	Note
	Created time.Time `ini:"-"`
}

func main() {
	cfg, err := ini.Load("path/to/ini")
	// ...
	p := new(Person)
	err = cfg.MapTo(p)
	// ...

	// Things can be simpler.
	err = ini.MapTo(p, "path/to/ini")
	// ...

	// Just map a section? Fine.
	n := new(Note)
	err = cfg.Section("Note").MapTo(n)
	// ...
}

Can I have default value for field? Absolutely.

Assign it before you map to struct. It will keep the value as it is if the key is not presented or got wrong type.

// ...
p := &Person{
	Name: "Joe",
}
// ...

It's really cool, but what's the point if you can't give me my file back from struct?

Reflect From Struct

Why not?

type Embeded struct {
	Dates  []time.Time `delim:"|" comment:"Time data"`
	Places []string    `ini:"places,omitempty"`
	None   []int       `ini:",omitempty"`
}

type Author struct {
	Name      string `ini:"NAME"`
	Male      bool
	Age       int `comment:"Author's age"`
	GPA       float64
	NeverMind string `ini:"-"`
	*Embeded `comment:"Embeded section"`
}

func main() {
	a := &Author{"Unknwon", true, 21, 2.8, "",
		&Embeded{
			[]time.Time{time.Now(), time.Now()},
			[]string{"HangZhou", "Boston"},
			[]int{},
		}}
	cfg := ini.Empty()
	err = ini.ReflectFrom(cfg, a)
	// ...
}

So, what do I get?

NAME = Unknwon
Male = true
; Author's age
Age = 21
GPA = 2.8

; Embeded section
[Embeded]
; Time data
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
places = HangZhou,Boston
Name Mapper

To save your time and make your code cleaner, this library supports NameMapper between struct field and actual section and key name.

There are 2 built-in name mappers:

  • AllCapsUnderscore: it converts to format ALL_CAPS_UNDERSCORE then match section or key.
  • TitleUnderscore: it converts to format title_underscore then match section or key.

To use them:

type Info struct {
	PackageName string
}

func main() {
	err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("package_name=ini"))
	// ...

	cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
	// ...
	info := new(Info)
	cfg.NameMapper = ini.AllCapsUnderscore
	err = cfg.MapTo(info)
	// ...
}

Same rules of name mapper apply to ini.ReflectFromWithMapper function.

Value Mapper

To expand values (e.g. from environment variables), you can use the ValueMapper to transform values:

type Env struct {
	Foo string `ini:"foo"`
}

func main() {
	cfg, err := ini.Load([]byte("[env]\nfoo = ${MY_VAR}\n")
	cfg.ValueMapper = os.ExpandEnv
	// ...
	env := &Env{}
	err = cfg.Section("env").MapTo(env)
}

This would set the value of env.Foo to the value of the environment variable MY_VAR.

Other Notes On Map/Reflect

Any embedded struct is treated as a section by default, and there is no automatic parent-child relations in map/reflect feature:

type Child struct {
	Age string
}

type Parent struct {
	Name string
	Child
}

type Config struct {
	City string
	Parent
}

Example configuration:

City = Boston

[Parent]
Name = Unknwon

[Child]
Age = 21

What if, yes, I'm paranoid, I want embedded struct to be in the same section. Well, all roads lead to Rome.

type Child struct {
	Age string
}

type Parent struct {
	Name string
	Child `ini:"Parent"`
}

type Config struct {
	City string
	Parent
}

Example configuration:

City = Boston

[Parent]
Name = Unknwon
Age = 21

Getting Help

FAQs

What does BlockMode field do?

By default, library lets you read and write values so we need a locker to make sure your data is safe. But in cases that you are very sure about only reading data through the library, you can set cfg.BlockMode = false to speed up read operations about 50-70% faster.

Why another INI library?

Many people are using my another INI library goconfig, so the reason for this one is I would like to make more Go style code. Also when you set cfg.BlockMode = false, this one is about 10-30% faster.

To make those changes I have to confirm API broken, so it's safer to keep it in another place and start using gopkg.in to version my package at this time.(PS: shorter import path)

License

This project is under Apache v2 License. See the LICENSE file for the full license text.

Documentation

Overview

Package ini provides INI file read and write functionality in Go.

Index

Constants

View Source
const (
	// Name for default section. You can use this constant or the string literal.
	// In most of cases, an empty string is all you need to access the section.
	DEFAULT_SECTION = "DEFAULT"
)

Variables

View Source
var (
	// Delimiter to determine or compose a new line.
	// This variable will be changed to "\r\n" automatically on Windows
	// at package init time.
	LineBreak = "\n"

	// Indicate whether to align "=" sign with spaces to produce pretty output
	// or reduce all possible spaces for compact format.
	PrettyFormat = true

	// Explicitly write DEFAULT section header
	DefaultHeader = false

	// Indicate whether to put a line between sections
	PrettySection = true
)

Functions

func IsErrDelimiterNotFound added in v1.21.0

func IsErrDelimiterNotFound(err error) bool

func MapTo

func MapTo(v, source interface{}, others ...interface{}) error

MapTo maps data sources to given struct.

func MapToWithMapper

func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error

MapTo maps data sources to given struct with name mapper.

func ReflectFrom

func ReflectFrom(cfg *File, v interface{}) error

ReflectFrom reflects data sources from given struct.

func ReflectFromWithMapper

func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error

ReflectFrom reflects data sources from given struct with name mapper.

func StrictMapTo added in v1.28.0

func StrictMapTo(v, source interface{}, others ...interface{}) error

StrictMapTo maps data sources to given struct in strict mode, which returns all possible error including value parsing error.

func StrictMapToWithMapper added in v1.28.0

func StrictMapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error

StrictMapToWithMapper maps data sources to given struct with name mapper in strict mode, which returns all possible error including value parsing error.

func Version

func Version() string

Version returns current package version literal.

Types

type ErrDelimiterNotFound added in v1.21.0

type ErrDelimiterNotFound struct {
	Line string
}

func (ErrDelimiterNotFound) Error added in v1.21.0

func (err ErrDelimiterNotFound) Error() string

type File

type File struct {

	// Should make things safe, but sometimes doesn't matter.
	BlockMode bool

	NameMapper
	ValueMapper
	// contains filtered or unexported fields
}

File represents a combination of a or more INI file(s) in memory.

func Empty

func Empty() *File

Empty returns an empty file object.

func InsensitiveLoad added in v1.14.0

func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error)

InsensitiveLoad has exactly same functionality as Load function except it forces all section and key names to be lowercased.

func Load

func Load(source interface{}, others ...interface{}) (*File, error)

Load loads and parses from INI data sources. Arguments can be mixed of file name with string type, or raw data in []byte. It will return error if list contains nonexistent files.

func LoadSources added in v1.14.0

func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error)

func LooseLoad added in v1.10.0

func LooseLoad(source interface{}, others ...interface{}) (*File, error)

LooseLoad has exactly same functionality as Load function except it ignores nonexistent files instead of returning error.

func ShadowLoad added in v1.25.2

func ShadowLoad(source interface{}, others ...interface{}) (*File, error)

InsensitiveLoad has exactly same functionality as Load function except it allows have shadow keys.

func (*File) Append

func (f *File) Append(source interface{}, others ...interface{}) error

Append appends one or more data sources and reloads automatically.

func (*File) ChildSections added in v1.27.0

func (f *File) ChildSections(name string) []*Section

ChildSections returns a list of child sections of given section name.

func (*File) DeleteSection

func (f *File) DeleteSection(name string)

DeleteSection deletes a section.

func (*File) GetSection

func (f *File) GetSection(name string) (*Section, error)

GetSection returns section by given name.

func (*File) MapTo

func (f *File) MapTo(v interface{}) error

MapTo maps file to given struct.

func (*File) NewRawSection added in v1.22.0

func (f *File) NewRawSection(name, body string) (*Section, error)

NewRawSection creates a new section with an unparseable body.

func (*File) NewSection

func (f *File) NewSection(name string) (*Section, error)

NewSection creates a new section.

func (*File) NewSections

func (f *File) NewSections(names ...string) (err error)

NewSections creates a list of sections.

func (*File) ReflectFrom

func (f *File) ReflectFrom(v interface{}) error

ReflectFrom reflects file from given struct.

func (*File) Reload

func (f *File) Reload() (err error)

Reload reloads and parses all data sources.

func (*File) SaveTo

func (f *File) SaveTo(filename string) error

SaveTo writes content to file system.

func (*File) SaveToIndent

func (f *File) SaveToIndent(filename, indent string) error

SaveToIndent writes content to file system with given value indention.

func (*File) Section

func (f *File) Section(name string) *Section

Section assumes named section exists and returns a zero-value when not.

func (*File) SectionStrings

func (f *File) SectionStrings() []string

SectionStrings returns list of section names.

func (*File) Sections

func (f *File) Sections() []*Section

Section returns list of Section.

func (*File) StrictMapTo added in v1.28.0

func (f *File) StrictMapTo(v interface{}) error

MapTo maps file to given struct in strict mode, which returns all possible error including value parsing error.

func (*File) WriteTo

func (f *File) WriteTo(w io.Writer) (int64, error)

WriteTo writes file content into io.Writer.

func (*File) WriteToIndent

func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error)

WriteToIndent writes content into io.Writer with given indention. If PrettyFormat has been set to be true, it will align "=" sign with spaces under each section.

type Key

type Key struct {
	Comment string
	// contains filtered or unexported fields
}

Key represents a key under a section.

func (*Key) AddNestedValue added in v1.32.0

func (k *Key) AddNestedValue(val string) error

func (*Key) AddShadow added in v1.25.0

func (k *Key) AddShadow(val string) error

AddShadow adds a new shadow key to itself.

func (*Key) Bool

func (k *Key) Bool() (bool, error)

Bool returns bool type value.

func (*Key) Duration

func (k *Key) Duration() (time.Duration, error)

Duration returns time.Duration type value.

func (*Key) Float64

func (k *Key) Float64() (float64, error)

Float64 returns float64 type value.

func (*Key) Float64s

func (k *Key) Float64s(delim string) []float64

Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value.

func (*Key) In

func (k *Key) In(defaultVal string, candidates []string) string

In always returns value without error, it returns default value if error occurs or doesn't fit into candidates.

func (*Key) InFloat64

func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64

InFloat64 always returns value without error, it returns default value if error occurs or doesn't fit into candidates.

func (*Key) InInt

func (k *Key) InInt(defaultVal int, candidates []int) int

InInt always returns value without error, it returns default value if error occurs or doesn't fit into candidates.

func (*Key) InInt64

func (k *Key) InInt64(defaultVal int64, candidates []int64) int64

InInt64 always returns value without error, it returns default value if error occurs or doesn't fit into candidates.

func (*Key) InTime

func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time

InTime always parses with RFC3339 format and returns value without error, it returns default value if error occurs or doesn't fit into candidates.

func (*Key) InTimeFormat

func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time

InTimeFormat always parses with given format and returns value without error, it returns default value if error occurs or doesn't fit into candidates.

func (*Key) InUint

func (k *Key) InUint(defaultVal uint, candidates []uint) uint

InUint always returns value without error, it returns default value if error occurs or doesn't fit into candidates.

func (*Key) InUint64

func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64

InUint64 always returns value without error, it returns default value if error occurs or doesn't fit into candidates.

func (*Key) Int

func (k *Key) Int() (int, error)

Int returns int type value.

func (*Key) Int64

func (k *Key) Int64() (int64, error)

Int64 returns int64 type value.

func (*Key) Int64s

func (k *Key) Int64s(delim string) []int64

Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value.

func (*Key) Ints

func (k *Key) Ints(delim string) []int

Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value.

func (*Key) MustBool

func (k *Key) MustBool(defaultVal ...bool) bool

MustBool always returns value without error, it returns false if error occurs.

func (*Key) MustDuration

func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration

MustDuration always returns value without error, it returns zero value if error occurs.

func (*Key) MustFloat64

func (k *Key) MustFloat64(defaultVal ...float64) float64

MustFloat64 always returns value without error, it returns 0.0 if error occurs.

func (*Key) MustInt

func (k *Key) MustInt(defaultVal ...int) int

MustInt always returns value without error, it returns 0 if error occurs.

func (*Key) MustInt64

func (k *Key) MustInt64(defaultVal ...int64) int64

MustInt64 always returns value without error, it returns 0 if error occurs.

func (*Key) MustString

func (k *Key) MustString(defaultVal string) string

MustString returns default value if key value is empty.

func (*Key) MustTime

func (k *Key) MustTime(defaultVal ...time.Time) time.Time

MustTime always parses with RFC3339 format and returns value without error, it returns zero value if error occurs.

func (*Key) MustTimeFormat

func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time

MustTimeFormat always parses with given format and returns value without error, it returns zero value if error occurs.

func (*Key) MustUint

func (k *Key) MustUint(defaultVal ...uint) uint

MustUint always returns value without error, it returns 0 if error occurs.

func (*Key) MustUint64

func (k *Key) MustUint64(defaultVal ...uint64) uint64

MustUint64 always returns value without error, it returns 0 if error occurs.

func (*Key) Name

func (k *Key) Name() string

Name returns name of key.

func (*Key) NestedValues added in v1.32.0

func (k *Key) NestedValues() []string

NestedValues returns nested values stored in the key. It is possible returned value is nil if no nested values stored in the key.

func (*Key) RangeFloat64

func (k *Key) RangeFloat64(defaultVal, min, max float64) float64

RangeFloat64 checks if value is in given range inclusively, and returns default value if it's not.

func (*Key) RangeInt

func (k *Key) RangeInt(defaultVal, min, max int) int

RangeInt checks if value is in given range inclusively, and returns default value if it's not.

func (*Key) RangeInt64

func (k *Key) RangeInt64(defaultVal, min, max int64) int64

RangeInt64 checks if value is in given range inclusively, and returns default value if it's not.

func (*Key) RangeTime

func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time

RangeTime checks if value with RFC3339 format is in given range inclusively, and returns default value if it's not.

func (*Key) RangeTimeFormat

func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time

RangeTimeFormat checks if value with given format is in given range inclusively, and returns default value if it's not.

func (*Key) SetValue

func (k *Key) SetValue(v string)

SetValue changes key value.

func (*Key) StrictFloat64s added in v1.9.0

func (k *Key) StrictFloat64s(delim string) ([]float64, error)

StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input.

func (*Key) StrictInt64s added in v1.9.0

func (k *Key) StrictInt64s(delim string) ([]int64, error)

StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input.

func (*Key) StrictInts added in v1.9.0

func (k *Key) StrictInts(delim string) ([]int, error)

StrictInts returns list of int divided by given delimiter or error on first invalid input.

func (*Key) StrictTimes added in v1.9.0

func (k *Key) StrictTimes(delim string) ([]time.Time, error)

StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter or error on first invalid input.

func (*Key) StrictTimesFormat added in v1.9.0

func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error)

StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter or error on first invalid input.

func (*Key) StrictUint64s added in v1.9.0

func (k *Key) StrictUint64s(delim string) ([]uint64, error)

StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input.

func (*Key) StrictUints added in v1.9.0

func (k *Key) StrictUints(delim string) ([]uint, error)

StrictUints returns list of uint divided by given delimiter or error on first invalid input.

func (*Key) String

func (k *Key) String() string

String returns string representation of value.

func (*Key) Strings

func (k *Key) Strings(delim string) []string

Strings returns list of string divided by given delimiter.

func (*Key) StringsWithShadows added in v1.25.3

func (k *Key) StringsWithShadows(delim string) []string

StringsWithShadows returns list of string divided by given delimiter. Shadows will also be appended if any.

func (*Key) Time

func (k *Key) Time() (time.Time, error)

Time parses with RFC3339 format and returns time.Time type value.

func (*Key) TimeFormat

func (k *Key) TimeFormat(format string) (time.Time, error)

TimeFormat parses with given format and returns time.Time type value.

func (*Key) Times

func (k *Key) Times(delim string) []time.Time

Times parses with RFC3339 format and returns list of time.Time divided by given delimiter. Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).

func (*Key) TimesFormat

func (k *Key) TimesFormat(format, delim string) []time.Time

TimesFormat parses with given format and returns list of time.Time divided by given delimiter. Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).

func (*Key) Uint

func (k *Key) Uint() (uint, error)

Uint returns uint type valued.

func (*Key) Uint64

func (k *Key) Uint64() (uint64, error)

Uint64 returns uint64 type value.

func (*Key) Uint64s

func (k *Key) Uint64s(delim string) []uint64

Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value.

func (*Key) Uints

func (k *Key) Uints(delim string) []uint

Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value.

func (*Key) ValidFloat64s added in v1.9.0

func (k *Key) ValidFloat64s(delim string) []float64

ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then it will not be included to result list.

func (*Key) ValidInt64s added in v1.9.0

func (k *Key) ValidInt64s(delim string) []int64

ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer, then it will not be included to result list.

func (*Key) ValidInts added in v1.9.0

func (k *Key) ValidInts(delim string) []int

ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will not be included to result list.

func (*Key) ValidTimes added in v1.9.0

func (k *Key) ValidTimes(delim string) []time.Time

ValidTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter.

func (*Key) ValidTimesFormat added in v1.9.0

func (k *Key) ValidTimesFormat(format, delim string) []time.Time

ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter.

func (*Key) ValidUint64s added in v1.9.0

func (k *Key) ValidUint64s(delim string) []uint64

ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned integer, then it will not be included to result list.

func (*Key) ValidUints added in v1.9.0

func (k *Key) ValidUints(delim string) []uint

ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer, then it will not be included to result list.

func (*Key) Validate

func (k *Key) Validate(fn func(string) string) string

Validate accepts a validate function which can return modifed result as key value.

func (*Key) Value

func (k *Key) Value() string

Value returns raw value of key for performance purpose.

func (*Key) ValueWithShadows added in v1.25.0

func (k *Key) ValueWithShadows() []string

ValueWithShadows returns raw values of key and its shadows if any.

type LoadOptions added in v1.14.0

type LoadOptions struct {
	// Loose indicates whether the parser should ignore nonexistent files or return error.
	Loose bool
	// Insensitive indicates whether the parser forces all section and key names to lowercase.
	Insensitive bool
	// IgnoreContinuation indicates whether to ignore continuation lines while parsing.
	IgnoreContinuation bool
	// IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value.
	IgnoreInlineComment bool
	// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing.
	// This type of keys are mostly used in my.cnf.
	AllowBooleanKeys bool
	// AllowShadows indicates whether to keep track of keys with same name under same section.
	AllowShadows bool
	// AllowNestedValues indicates whether to allow AWS-like nested values.
	// Docs: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html#nested-values
	AllowNestedValues bool
	// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format
	// when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
	UnescapeValueDoubleQuotes bool
	// UnescapeValueCommentSymbols indicates to unescape comment symbols (\# and \;) inside value to regular format
	// when value is NOT surrounded by any quotes.
	// Note: UNSTABLE, behavior might change to only unescape inside double quotes but may noy necessary at all.
	UnescapeValueCommentSymbols bool
	// Some INI formats allow group blocks that store a block of raw content that doesn't otherwise
	// conform to key/value pairs. Specify the names of those blocks here.
	UnparseableSections []string
}

type NameMapper

type NameMapper func(string) string

NameMapper represents a ini tag name mapper.

var (
	// AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE.
	AllCapsUnderscore NameMapper = func(raw string) string {
		newstr := make([]rune, 0, len(raw))
		for i, chr := range raw {
			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
				if i > 0 {
					newstr = append(newstr, '_')
				}
			}
			newstr = append(newstr, unicode.ToUpper(chr))
		}
		return string(newstr)
	}
	// TitleUnderscore converts to format title_underscore.
	TitleUnderscore NameMapper = func(raw string) string {
		newstr := make([]rune, 0, len(raw))
		for i, chr := range raw {
			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
				if i > 0 {
					newstr = append(newstr, '_')
				}
				chr -= ('A' - 'a')
			}
			newstr = append(newstr, chr)
		}
		return string(newstr)
	}
)

Built-in name getters.

type Section

type Section struct {
	Comment string
	// contains filtered or unexported fields
}

Section represents a config section.

func (*Section) Body added in v1.22.0

func (s *Section) Body() string

Body returns rawBody of Section if the section was marked as unparseable. It still follows the other rules of the INI format surrounding leading/trailing whitespace.

func (*Section) ChildSections added in v1.27.0

func (s *Section) ChildSections() []*Section

ChildSections returns a list of child sections of current section. For example, "[parent.child1]" and "[parent.child12]" are child sections of section "[parent]".

func (*Section) DeleteKey

func (s *Section) DeleteKey(name string)

DeleteKey deletes a key from section.

func (*Section) GetKey

func (s *Section) GetKey(name string) (*Key, error)

GetKey returns key in section by given name.

func (*Section) HasKey

func (s *Section) HasKey(name string) bool

HasKey returns true if section contains a key with given name.

func (*Section) HasValue

func (s *Section) HasValue(value string) bool

HasValue returns true if section contains given raw value.

func (*Section) Haskey

func (s *Section) Haskey(name string) bool

Haskey is a backwards-compatible name for HasKey. TODO: delete me in v2

func (*Section) Key

func (s *Section) Key(name string) *Key

Key assumes named Key exists in section and returns a zero-value when not.

func (*Section) KeyStrings

func (s *Section) KeyStrings() []string

KeyStrings returns list of key names of section.

func (*Section) Keys

func (s *Section) Keys() []*Key

Keys returns list of keys of section.

func (*Section) KeysHash

func (s *Section) KeysHash() map[string]string

KeysHash returns keys hash consisting of names and values.

func (*Section) MapTo

func (s *Section) MapTo(v interface{}) error

MapTo maps section to given struct.

func (*Section) Name

func (s *Section) Name() string

Name returns name of Section.

func (*Section) NewBooleanKey added in v1.24.0

func (s *Section) NewBooleanKey(name string) (*Key, error)

NewBooleanKey creates a new boolean type key to given section.

func (*Section) NewKey

func (s *Section) NewKey(name, val string) (*Key, error)

NewKey creates a new key to given section.

func (*Section) ParentKeys added in v1.12.0

func (s *Section) ParentKeys() []*Key

ParentKeys returns list of keys of parent section.

func (*Section) ReflectFrom

func (s *Section) ReflectFrom(v interface{}) error

ReflectFrom reflects secion from given struct.

func (*Section) SetBody added in v1.30.3

func (s *Section) SetBody(body string)

SetBody updates body content only if section is raw.

func (*Section) StrictMapTo added in v1.28.0

func (s *Section) StrictMapTo(v interface{}) error

MapTo maps section to given struct in strict mode, which returns all possible error including value parsing error.

type ValueMapper added in v1.20.0

type ValueMapper func(string) string

ValueMapper represents a mapping function for values, e.g. os.ExpandEnv

Jump to

Keyboard shortcuts

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