This project is considered stable GoDoc Build Status codecov

sconfig is a simple and functional configuration file parser for Go.


go get arp242.net/sconfig

Go 1.5 and newer should work, but the test suite only runs with 1.7 and newer.

What does it look like?

A file like this:

# This is a comment

port 8080 # This is also a comment

# Look ma, no quotes!
base-url http://example.com

# We'll parse these in a []*regexp.Regexp
match ^foo.+
match ^b[ao]r

# Two values
order allow deny

host  # Idented lines are collapsed
	arp242.net         # My website
	stackoverflow.com  # I like this too

address arp242.net

Can be parsed with:

package main

import (


	// Types that need imports are in handlers/pkgname
	_ "arp242.net/sconfig/handlers/regexp"

type Config struct {
	Port    int64
	BaseURL string
	Match   []*regexp.Regexp
	Order   []string
	Hosts   []string
	Address string

func main() {
	config := Config{}
	err := sconfig.Parse(&config, "config", sconfig.Handlers{
		// Custom handler
		"address": func(line []string) error {
			addr, err := net.LookupHost(line[0])
			if err != nil {
				return err

			config.Address = addr[0]
			return nil

	if err != nil {
		fmt.Fprintf(os.Stderr, "Error parsing config: %v", err)

	fmt.Printf("%#v\n", config)

But why not…

How do I…

Validate fields?

TODO: Mention chainable handlers here. There is no built-in way to do this. You can use if statements :-)

Maybe I’ll add this at a later date, an early (unreleased) version actually had tag-based validation, but I removed it as it added a bunch of complexity and I’m not at all sure this is a common enough problem that needs solving.

Besides, there are are several libraries that already do a good job at that such as validator, go-validation, govalidator, and others.

Set default values?

Just set them before parsing:

c := MyConfig{Value: "The default"}
sconfig.Parse(&c, "a-file", sconfig.Handlers{})

Use int types? I get an error?

Only int64 and uint64 are handled by default; this should be fine for almost all use cases of this package. If you want to add any of the other (u)int types you can do easily with your own type handler :-)

Note that the size of int and uint are platform-dependent, so adding those may not be a good idea.

I get a “don’t know how to set fields of the type …” error if I try to add a new type handler

Include the package name; even if the type handler is in the same package. Do:

sconfig.RegisterType("[]main.RecordT", func(v []string) (interface{}, error) {

and not:

sconfig.RegisterType("[]RecordT", func(v []string) (interface{}, error) {

Replace main with the appropriate package name.


The syntax of the file is very simple.


Reading the file

Programs using it


Aside from those mentioned in the “But why not…” section above:

Copyright © 2010-2017 Martin Tournoij <martin@arp242.net>
This document is licensed under a cc-by 4.0 license.