conf

package module
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Mar 22, 2025 License: MIT Imports: 7 Imported by: 0

README

module conf

go get code.uint32.ru/tiny/conf to download.

import "code.uint32.ru/tiny/conf" to use in your code.

Module conf implements a very simple config parser with two types of values: key value pairs and single word options. Each of these must be put on separate line in a file like this:

key1 = value
key2 = value1, value2, value3
option1
option2

Values can also be read from any io.Reader or io.ReadCloser. Note that values in key value pairs mey either be separated with spaces or not.

Typical use case would look like this:

config, err := conf.ParseFile("filename")
if err != nil {
	// Means we failed to read from file
	// config variable is now nil and unusable
}
value, err := config.Find("mykey")
if err != nil {
	// Means that key has not been found
}
// value now holds conf.Setting type which can be accessed directly.
fmt.Println(value.Value)
n, err := value.Float64() // tries to parse float from Setting.Value field.
// if err is nil then n holds float64.

Shorter syntax is also available with Get() method which drops errors if key was not found and simply returns Setting with empty Value field:

listnumbers, err := config.Get("numbers").IntSlice()
// listnumbers holds slice of ints. If err is nil all of found values
// have converted successfully.

Note that we'd still like to check for errors in above example even if we're sure the key exists. This way we'll configrm that all values have been converted.

There is also a GetDefault() method:

def := config.GetDefault("non-existant-key", "myvalue")
fmt.Println(def.Value) // "myvalue"

To check whether single-word options were found use:

if config.HasOption("wordoption") {
	// do something
}

See description of module's types and methods which are quite self-explanatory.

See also https://pkg.go.dev/code.uint32.ru/tiny/conf for a complete description of module's functions.

Below is listing of a working example of a program parsing config (also found example/main.go in the repository).

package main

import (
	"bytes"
	"fmt"

	"code.uint32.ru/tiny/conf"
)

var testConf = []byte(`
# commented
port=10000
servers = 10.0.0.1, 10.0.0.2, 10.0.0.3
bool0=0
booltrue = true
distance=13.42
iamsure = hopefully you're not mistaken
float = 13.1984
color`)

func main() {
	r := bytes.NewReader(testConf) // creating io.Reader from []byte()
	config := conf.ParseReader(r)  // we could call conf.ParseFile("filename") here

	// First of all we can access parsed values directly:
	for key, value := range config.Settings {
		fmt.Println(key, value)
	}
	for opt := range config.Options {
		fmt.Println(opt)
	}
	fmt.Println()

	// Find( key string) returns instance of Setting and an
	// error if key was not found
	//
	// type Setting struct {
	// 		Value 	string	// value if found
	// }
	//
	// You can access Setting's Value field (type string) directly.
	port, err := config.Find("port")
	fmt.Printf("variable port has type: %T, port.Value == %v, type of port.Value is: %T, error returned: %v\n", port, port.Value, port.Value, err)

	// We can cast Setting.Value to a desired type including int, float64,
	// bool and string. Method will return an error if Setting Value field
	// can not be interpreted as desired type.
	n, err := port.Int()
	fmt.Printf("n has value: %v, type: %T, err: %v\n", n, n, err)

	// Another syntax for getting Setting instance is to use Get() method
	// which never returns errors. Get will return Setting with empty string
	// in Value filed if requested key was now found.
	d := config.Get("distance")
	distance, err := d.Float64()
	fmt.Printf("var distance has value: %v, type: %T, error value: %v\n", distance, distance, err)

	// Get() syntax can be is slightly shorter if we're "sure" that key exists in
	// the config.
	sure := config.Get("iamsure").String() // String method never returns errors
	// or simply sure := config.Get("iamsure").Value:
	fmt.Println(sure)

	// or like this:
	fl, _ := config.Get("float").Float64() // we're dropping error here. Bad if value fails to convert.
	fmt.Println("fl, _ := config.Get(\"float\").Float64() Value of var fl is:", fl)

	// We can access comma-separated values of key like this:
	servers := config.Get("servers").StringSlice()
	fmt.Println("Found servers:")
	for i, s := range servers {
		fmt.Println(i+1, "\t", s)
	}
	// There is also a GetDefault() method which sets output Setting value
	// to requested default if key was not found.
	def := config.GetDefault("non-existant-key", "myvalue")
	fmt.Println(def.Value) // "myvalue"

	// You can use HasOption method to find whether single-word options were
	// present in the the config
	if config.HasOption("color") {
		fmt.Println("Hooray, we've found option \"color\"!")
		// do something useful
	}

	// Below code finds two keys with bool values in the Config
	// and outputs those.
	var t, f bool
	t, _ = config.Get("booltrue").Bool()
	f, _ = config.Get("bool0").Bool()
	fmt.Printf("t's type is: %T, value: %v, f's type is: %T, value: %v\n\n", t, t, f, f)
}

Here is the full output of the above code:

distance 13.42
iamsure hopefully you're not mistaken
float 13.1984
port 10000
servers 10.0.0.1, 10.0.0.2, 10.0.0.3
bool0 0
booltrue true
color

variable port has type: conf.Setting, port.Value == 10000, type of port.Value is: string, error returned: <nil>
n has value: 10000, type: int, err: <nil>
var distance has value: 13.42, type: float64, error value: <nil>
hopefully you're not mistaken
fl, _ := config.Get("float").Float64() Value of var fl is: 13.1984
Found servers:
1 	 10.0.0.1
2 	 10.0.0.2
3 	 10.0.0.3
Hooray, we've found option "color"!
t's type is: bool, value: true, f's type is: bool, value: false

Documentation

Overview

module conf

import "code.uint32.ru/tiny/conf"

Module conf implements a very simple config parser with two types of values: key value pairs and single word options. Each of these must be put on separate line in a file like this:

key1 = value
key2 = value1, value2, value3
key3=v1,v2,v3
option1
option2

Values can also be read from any io.Reader or io.ReadCloser. Note that values in key value pairs mey either be separated with spaces or not. Typical use case would look like this:

config, err := conf.ParseFile("filename")
if err != nil {
	// Means we failed to read from file
	// config variable is now nil and unusable
}
value, err := config.Find("mykey")
if err != nil {
	// Means that key has not been found
}
// value now holds conf.Setting.
n, err := value.Float64() // tries to parse float from Setting.Value field.
//if err is nil then n holds float64.

There is also a quicker Get() method which returns no errors ("i'm feeling lucky" way to lookup values). If it does not find requested key, the returned Setting has empty string in Value field.

value2 := config.Get("otherkey")
mybool, err := value2.Bool() // tries to interpret Setting.Value field as bool
// mybool now holds boolean if "otherkey" was found and error returned
// by Bool() method is nil.

Even shorter syntax would be:

listnumbers, err := config.Get("numbers").IntSlice()
// Note that we'd still like to check for errors even if
// we're sure the key exists to make sure all values are converted.
// listnumbers holds slice of ints. If err is nil all of found values
// have been converted successfully.

To check whether single-word options were found use:

if config.HasOption("wordoption") {
	// do something
}

See description of module's other methods which are quite self-explanatory.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNotFound        = errors.New("key not found")
	ErrParsingBool     = errors.New("value can not be interpreted as bool")
	ErrCouldNotConvert = errors.New("could not cast one or more values to required type")
)

Functions

This section is empty.

Types

type Config

type Config struct {
	// Settings store key value pairs ("key = value" in config file)
	// all key value pairs found when parsing input are accumulated in this map.
	Settings map[string]string
	// Options map stores single word options ("option" in config file)
	Options map[string]struct{}
}

Config holds parsed keys and values. Settings and Options can be accessed with Config.Settings and Config.Options maps directly.

func ParseFile

func ParseFile(filename string) (*Config, error)

ParseFile reads values from file. It returns nil and error if os.Open(filename) fails. It would be wise to always check returned error. ParseFile captures two types of values: "key = value" and "option". Either key value pair or option must be put in its own line in the file. Key or option must be a single word. In example line:

"option1 option2"

only option1 will be captured. option2 needs to be in a separate line in the file to take effect. In line "key = value1,value2,value3" all of value1, value2, and value3 will be captured. They can be later accesed separately with Setting's Split() method.

func ParseReadCloser

func ParseReadCloser(r io.ReadCloser) *Config

ParseReadCloser reads from r, returns Config and calls r.Close(). See also ParseFile.

func ParseReader

func ParseReader(r io.Reader) *Config

ParseReader reads from r and returns Config. See also ParseFile.

func (*Config) Find

func (c *Config) Find(key string) (s Setting, err error)

Find looks up a Setting and returns it. If returned error is not nil the requested key was not found and returned Setting has empty string in Value field.

func (*Config) Get

func (c *Config) Get(key string) (s Setting)

Get returns a Setting. If key was not found the returned Setting Value will be empty string.

func (*Config) GetDefault

func (c *Config) GetDefault(key, def string) (s Setting)

GetDefault looks up a Setting with requested key. If lookup fails it returns Setting with Value field set to def.

func (*Config) HasOption

func (c *Config) HasOption(option string) (exists bool)

HasOption returns true if line:

"key"

was found in the parsed file

type Setting

type Setting struct {
	Value string
}

Setting represents key-value pair read from config file. It's Value field holds the value of key parsed from the configuration

func (Setting) Bool

func (st Setting) Bool() (bool, error)

Bool tries to interpret Setting's Value as bool "1", "true", "on", "yes" (case insensitive) yields true "0", "false", "off", "no" (case insensitive) yields false If nothing matches will return false and conf.ErrParsingBool

func (Setting) Float64

func (st Setting) Float64() (float64, error)

Float64 converts Setting Value to float64. Returned error will be non nil if convesion failed.

func (Setting) Float64Slice

func (st Setting) Float64Slice() ([]float64, error)

Float64Slice splits Setting Value (separator is ",") and adds each of resulting values to []float64 if possible. If one or more values can not be converted to float64 those will be dropped and method will return conf.ErrCouldNotConvert. Check error to be sure that all required values were parsed.

func (Setting) Int

func (st Setting) Int() (int, error)

Int converts Setting Value to int. Returned error will be non nil if convesion failed.

func (Setting) IntSlice

func (st Setting) IntSlice() ([]int, error)

IntSlice splits Setting Value (separator is ",") and adds each of resulting values to []int if possible. If one or more values can not be converted to float64 those will be dropped and method will return conf.ErrCouldNotConvert. Check error to be sure that all required values were parsed.

func (Setting) String

func (st Setting) String() string

String returns option Value as string This method also implements Stringer interface from fmt module

func (Setting) StringSlice

func (st Setting) StringSlice() []string

StringSlice splits Setting's Value (separator is ",") and adds each of resulting values to []string trimming leading and trailing spaces from each string.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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