Documentation ¶
Overview ¶
Read/Write settings from a .ini formatted configuration file.
This package allows for .ini text files to be created, loaded, reloaded, saved and updated. It also allows for notifications to be sent to observers when sections or keys change either explictly via calls to the instance, or via a call to Reload()
When saving/updating files it preserves the original order of entries that were in the file on disk at the point it's saved, along with any comments and spacing contained in it.
The IniConf type reads and writes .ini files and provides access to their contents.
The ChainConf type allows multiple .ini files (on disk or in memory) to be chained together, allowing for in-memory defaults to be overriden by an on-disk configuration file.
Index ¶
- Constants
- Variables
- type ConfChain
- func (cc *ConfChain) AddConf(i *IniConf)
- func (cc *ConfChain) EntryBool(sectionName, entryName string) (bool, error)
- func (cc *ConfChain) EntryBoolP(sectionName, entryName string) bool
- func (cc *ConfChain) EntryInt(sectionName, entryName string) (int64, error)
- func (cc *ConfChain) EntryIntP(sectionName, entryName string) int64
- func (cc *ConfChain) EntryString(sectionName, entryName string) (string, error)
- func (cc *ConfChain) EntryStringP(sectionName, entryName string) string
- func (cc *ConfChain) HasSection(sectionName string) bool
- func (cc *ConfChain) ReadSection(sectionName string, v interface{}) error
- type DeleteSectionObserver
- type EntryChangeObserver
- type IniConf
- func LoadEnviron(prefix string, caseSensitive bool) (*IniConf, error)
- func LoadFile(filename string, caseSensitive bool) (*IniConf, error)
- func LoadReader(r io.Reader, caseSensitive bool) (*IniConf, error)
- func LoadString(s string, caseSensitive bool) (*IniConf, error)
- func New(caseSensitive bool) *IniConf
- func NewFile(filename string, caseSensitive bool) *IniConf
- func (i *IniConf) DeleteEntry(sectionName, entryName string) (err error)
- func (i *IniConf) DeleteSection(name string) error
- func (i *IniConf) DisableObservers()
- func (i *IniConf) EnableObservers()
- func (i *IniConf) EntryBool(sectionName, entryName string) (bool, error)
- func (i *IniConf) EntryInt(sectionName, entryName string) (int64, error)
- func (i *IniConf) EntryNames(sectionName string) (result []string)
- func (i *IniConf) EntryString(sectionName, entryName string) (string, error)
- func (i *IniConf) HasSection(sectionName string) bool
- func (i *IniConf) NewSection(name string) (err error)
- func (i *IniConf) ReadSection(sectionName string, v interface{}) error
- func (i *IniConf) RegisterGlobalObserver(ob interface{})
- func (i *IniConf) RegisterSectionObserver(sectionName string, ob interface{})
- func (i *IniConf) Reload() error
- func (i *IniConf) Save() error
- func (i *IniConf) SaveToFilename(filename string) error
- func (i *IniConf) Sections() []string
- func (i *IniConf) SetEntry(sectionName, entryName string, value interface{}) (err error)
- func (i *IniConf) String() string
- func (i *IniConf) UnregisterGlobalObserver(ob interface{})
- func (i *IniConf) UnregisterSectionObserver(sectionName string, ob interface{})
- func (i *IniConf) UpdateSection(sectionName string, v interface{}) error
- type NewSectionObserver
- type ParseError
Examples ¶
Constants ¶
const ( ErrInvalidSection = iota ErrInvalidEntry ErrLineTooLong ErrNoSection )
ParseError codes.
Variables ¶
var ( ErrDuplicateSection = errors.New("Duplicate section name") ErrInvalidEntryName = errors.New("Invalid name used for entry") ErrEntryNotFound = errors.New("Entry not found in section") ErrSectionNotFound = errors.New("Section not found") ErrReloadNoFilename = errors.New("Cannot reload; no filename specified") ErrSaveNoFilename = errors.New("Cannot save; no filename specified") ErrEmptyEntryValue = errors.New("Cannot assign empty string to an entry") ErrBadObserver = errors.New("Attempted to register observer that does not implement an observer interface") ErrEmptyConfChain = errors.New("ConfChain has no configuration files") )
var ( ErrInvalidType = errors.New("target must be a pointer") ErrInvalidFieldType = errors.New("target must be a string, int or bool") )
Functions ¶
This section is empty.
Types ¶
type ConfChain ¶
type ConfChain struct {
// contains filtered or unexported fields
}
A ConfChain reads sequentially from a list of IniConf configurations, returning a result from the first IniConf that has a value set for a requested setting.
Useful if you want a .ini file on disk to override an in-memory set of defaults.
Example ¶
This example creates two configuration files (though could just as easily load one or more from file using LoadFile()) and chains them together so that calls to EntryString() will attempt to fetch a value from the primary config file first, and then fallback to reading from the default.
There's no limit to the number of config files you can have in a chain
package main import ( "fmt" "github.com/gwatts/iniconf" ) func main() { var primaryConfText = ` [section one] key1 = val1 ` var defaultConfText = ` [section one] key1 = default1 key2 = default2 ` // Load our primary and default config files primaryConf, _ := iniconf.LoadString(primaryConfText, true) defaultConf, _ := iniconf.LoadString(defaultConfText, true) // create the chain chain := iniconf.NewConfChain(primaryConf, defaultConf) // key1 will be read from the primary key1, _ := chain.EntryString("section one", "key1") // primary doesn't have key2 set, so will read from default key2, _ := chain.EntryString("section one", "key2") fmt.Println("key1:", key1) fmt.Println("key2:", key2) }
Output: key1: val1 key2: default2
func NewConfChain ¶
Create a new chain.
IniConfs will be read from in preference from first to last specified here ie. the IniConf holding the default values to fallback to should be the last argument to this function.
func (*ConfChain) AddConf ¶
AddConf adds an additional IniConf file to the chain at a lower priority than those already configured.
func (*ConfChain) EntryBool ¶
Fetch a boolean entry from a section from the first IniConf that returns a value.
func (*ConfChain) EntryBoolP ¶
EntryBoolP fetches a boolean entry from a section from the first IniConf that returns a value.
Unlike EntryBool(), It panics if no IniConfs contain the setting.
func (*ConfChain) EntryInt ¶
EntryInt fetches an integer entry from a section from the first IniConf that returns a value.
func (*ConfChain) EntryIntP ¶
EntryIntP fetches an integer entry from a section from the first IniConf that returns a value.
Unlike EntryInt(), It panics if no IniConfs contain the setting.
func (*ConfChain) EntryString ¶
EntryString fetches a string entry from a section from the first IniConf that returns a value.
func (*ConfChain) EntryStringP ¶
EntryStringP fetches a string entry from a section from the first IniConf that returns a value.
Unlike EntryString(), It panics if no IniConfs contain the setting.
func (*ConfChain) HasSection ¶
func (*ConfChain) ReadSection ¶
ReadSection maps an IniConf section into a struct
Each field in the struct to be read from the section should be tagged with `iniconf:"keyname"`
Only string, bool and int types are supported ¶
Nested structs are flattened into the parent's namespace.
type DeleteSectionObserver ¶
Types implementing the DeleteSectionObserver interface may be passed to RegisterGlobalObserver or RegisterSectionObserver to be advised of sections being deleted.
type EntryChangeObserver ¶
type EntryChangeObserver interface {
IniEntryChanged(i *IniConf, sectionName, entryName, oldValue, newValue string)
}
Types implementing the EntryChangeObserver interface may be passed to RegisterGlobalObserver or RegisterSectionObserver to be advised of entries within sections being added, removed or updated.
New entries will have an empty oldValue. Deleted entries will have an empty newValue.
type IniConf ¶
type IniConf struct {
// contains filtered or unexported fields
}
An IniConf holds configuration information read from a file in .ini format.
ini files are made up of sections containing entry keys and values.
All public methods of IniConf are safe to use from concurrent goroutines.
This implementation supports line comments beginning with a semi colon and multi-line values where the second and subsequent lines for the value begin with a space.
Keys and values may be any UTF8 strings.
Comments inline with a value are not supported.
Example ¶
package main import ( "fmt" "io/ioutil" "os" "github.com/gwatts/iniconf" ) func main() { // create an example configuration file to work with var exampleConf = ` [section one] key1 = val1 ` tf, err := ioutil.TempFile(os.TempDir(), "iniconf") if err != nil { fmt.Println("Failed to create tempfile:", err) } defer os.Remove(tf.Name()) tf.Write([]byte(exampleConf)) tf.Close() // Load the configuration file conf, err := iniconf.LoadFile(tf.Name(), true) if err != nil { fmt.Println("Failed to load file:", err) } // Print the current value of section1, key1 key1, err := conf.EntryString("section one", "key1") if err != nil { fmt.Println("Couldn't read key1:", err) return } fmt.Println("Key1 is currently set to", key1) // Update key1 conf.SetEntry("section one", "key1", "new value") // Add another key in another section conf.SetEntry("new section", "some number", 42) // Save it err = conf.Save() if err != nil { fmt.Println("Failed to save configuration file:", err) } fmt.Println("File saved") }
Output: Key1 is currently set to val1 File saved
func LoadEnviron ¶
LoadEnviron loads a .ini file from environment variables.
Each environment variable must in the format: prefix__section__key=value
func LoadFile ¶
LoadFile loads a .ini file from an existing file on disk. / Once loaded it can be edited and saved by calling Save().
func New ¶
New creates a new unnamed .ini file.
Specifying caseSensitive=true causes section and entry names to be cAsE sensitive (ie. section1 and Section1 map to two different sections)
Use SaveToFilename() to save.
func NewFile ¶
NewFile creates a new .ini file with defined filename.
Use Save() to write the contents to disk.
func (*IniConf) DeleteEntry ¶
DeleteEntry delets an entry from a section.
Will return a ErrEntryNotFound error if the entry doesn't exist.
func (*IniConf) DeleteSection ¶
DeleteSection deletes a section and all of its entries.
Will return ErrSectionNotFound if the section doesn't exist.
func (*IniConf) DisableObservers ¶
func (i *IniConf) DisableObservers()
DisableObservers temporarily disables observer notifications. Any notifications that would of been generated after this call has been made will be discarded.
func (*IniConf) EnableObservers ¶
func (i *IniConf) EnableObservers()
EnableObservers re-enables all observers.
func (*IniConf) EntryBool ¶
EntryBool an entry from the section as a boolean.
Returns a ErrEntryNotFound error if the entry isn't in the section.
func (*IniConf) EntryInt ¶
EntryInt fetches an entry from the section as integer.
Returns a ErrEntryNotFound error if the entry isn't in the section.
func (*IniConf) EntryNames ¶
EntryNames returns a list of the entry names defined in a section.
Returns nil if the section does not exist.
func (*IniConf) EntryString ¶
EntryString fetches an entry from a section as a string.
Returns a ErrEntryNotFound error if the entry isn't in the section.
func (*IniConf) HasSection ¶
HasSection returns true if the section is defined in the configuration even if the section contains no entries.
func (*IniConf) NewSection ¶
NewSection creates a new empty section. It returns ErrDuplicateSection if the section already exists.
Note: If you just want to add a new entry to a section that doesn't yet exist then you can just call SetEntry() directly and the section will be auto-created.
func (*IniConf) ReadSection ¶
ReadSection maps an IniConf section into a struct
Each field in the struct to be read from the section should be tagged with `iniconf:"keyname"`
Only string, bool and int types are supported ¶
Nested structs are flattened into the parent's namespace.
Example ¶
package main import "fmt" import "github.com/gwatts/iniconf" var inifile = ` [mysection] value1 = First value num1 = 123 bool1 = true subvalue = nested value ` type section struct { Value1 string `iniconf:"value1"` Num1 int `iniconf:"num1"` Bool1 bool `iniconf:"bool1"` Sub struct { SubValue string `iniconf:"subvalue"` } } func main() { var s section cfg, _ := iniconf.LoadString(inifile, false) if err := cfg.ReadSection("mysection", &s); err != nil { fmt.Println("Failed", err) return } fmt.Println("Value1:", s.Value1) fmt.Println("Num1:", s.Num1) fmt.Println("Bool1:", s.Bool1) fmt.Println("Sub:", s.Sub.SubValue) }
Output: Value1: First value Num1: 123 Bool1: true Sub: nested value
func (*IniConf) RegisterGlobalObserver ¶
func (i *IniConf) RegisterGlobalObserver(ob interface{})
RegisterGlobalRegister registers an observer to be notified of all section and/or entry updates.
The observer must implement one or more of the NewSectionObserver, DeleteSectionObserver and EntryChangeObserver interfaces. Additionally you should pass a pointer to that observer to this method else UnregisterObserver will fail to remove the observer.
func (*IniConf) RegisterSectionObserver ¶
RegisterSectionObserver registers an observer to be notified of changes to a named section, whether or not it exists yet.
The observer must implement one or more of the NewSectionObserver, DeleteSectionObserver and EntryChangeObserver interfaces. Additionally you should pass a pointer to that observer to this method else UnregisterObserver will fail to remove the observer.
func (*IniConf) Reload ¶
Reload the configuration file by re-reading the file from disk. The .ini file must either have been created using LoadFile() or have been saved using SaveToFilename() for a reload to succeed.
Any unsaved changes will be lost.
func (*IniConf) Save ¶
Save the .ini file by updating any existing version on disk.
This will attempt to preserve the order of the entries in the original file along with comment in sections that weren't deleted.
The file must either have been initially loaded from file using LoadFile() or already been saved to a file using SaveToFilename().
func (*IniConf) SaveToFilename ¶
SaveToFilename save the IniConf to a new filename - Future calls to Save() will utilize the filename passed to this method.
func (*IniConf) SetEntry ¶
SetEntry creates or updates an entry in a section.
Non-string values will be converted to a string using the fmt package.
If a converted value, stripped of leading/trailing whitespace results in a string of length zero, then an ErrEmptyEntryValue error will be returned.
func (*IniConf) UnregisterGlobalObserver ¶
func (i *IniConf) UnregisterGlobalObserver(ob interface{})
UnregisterGlobalObserver unregisters a previously registered global observer.
func (*IniConf) UnregisterSectionObserver ¶
UnregisterSectionObserver unregisters a previously registered section observer.
func (*IniConf) UpdateSection ¶
UpdateSection takes a struct tagged with `iniconf:"keyname"` fields and loads those fields into the named section.
Nested structs are flattened into the parent's namespace.
Existing fields in the second that are not defined in the struct are left intact.
type NewSectionObserver ¶
Types implementing the RegisterSectionObserver interface may be passed to RegisterGlobalObserver or RegisterSectionObserver to be advised of new sections being created.
type ParseError ¶
type ParseError struct {
// contains filtered or unexported fields
}
A ParseError is created if a syntax error is found while reading an ini file.
Implements the error interface.
func (*ParseError) Code ¶
func (p *ParseError) Code() int
func (ParseError) Error ¶
func (pe ParseError) Error() string
Returns the error message including the line number.
func (*ParseError) LineNum ¶
func (p *ParseError) LineNum() int
Return the line number of the source file the error refers to
func (ParseError) Msg ¶
func (p ParseError) Msg() string
Return the base message of the error, excluding the line number use the Error() method to get a message that includes the line number.