• Stars
    star
    1,366
  • Rank 34,414 (Top 0.7 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created about 7 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Flags-first package for configuration

ff go.dev reference Latest Release Build Status

ff stands for flags-first, and provides an opinionated way to populate a flag.FlagSet with configuration data from the environment. By default, it parses only from the command line, but you can enable parsing from environment variables (lower priority) and/or a configuration file (lowest priority).

Building a commandline application in the style of kubectl or docker? Consider package ffcli, a natural companion to, and extension of, package ff.

Usage

Define a flag.FlagSet in your func main.

import (
	"flag"
	"os"
	"time"

	"github.com/peterbourgon/ff/v3"
)

func main() {
	fs := flag.NewFlagSet("my-program", flag.ContinueOnError)
	var (
		listenAddr = fs.String("listen-addr", "localhost:8080", "listen address")
		refresh    = fs.Duration("refresh", 15*time.Second, "refresh interval")
		debug      = fs.Bool("debug", false, "log debug information")
		_          = fs.String("config", "", "config file (optional)")
	)

Then, call ff.Parse instead of fs.Parse. Options are available to control parse behavior.

	err := ff.Parse(fs, os.Args[1:],
		ff.WithEnvVarPrefix("MY_PROGRAM"),
		ff.WithConfigFileFlag("config"),
		ff.WithConfigFileParser(ff.PlainParser),
	)

This example will parse flags from the commandline args, just like regular package flag, with the highest priority. (The flag's default value will be used only if the flag remains unset after parsing all provided sources of configuration.)

Additionally, the example will look in the environment for variables with a MY_PROGRAM prefix. Flag names are capitalized, and separator characters are converted to underscores. In this case, for example, MY_PROGRAM_LISTEN_ADDR would match to listen-addr.

Finally, if a -config file is specified, the example will try to parse it using the PlainParser, which expects files in this format.

listen-addr localhost:8080
refresh 30s
debug true

You could also use the JSONParser, which expects a JSON object.

{
	"listen-addr": "localhost:8080",
	"refresh": "30s",
	"debug": true
}

Or, you could write your own config file parser.

// ConfigFileParser interprets the config file represented by the reader
// and calls the set function for each parsed flag pair.
type ConfigFileParser func(r io.Reader, set func(name, value string) error) error

Flags and env vars

One common use case is to allow configuration from both flags and env vars.

package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/peterbourgon/ff/v3"
)

func main() {
	fs := flag.NewFlagSet("myservice", flag.ContinueOnError)
	var (
		port  = fs.Int("port", 8080, "listen port for server (also via PORT)")
		debug = fs.Bool("debug", false, "log debug information (also via DEBUG)")
	)
	if err := ff.Parse(fs, os.Args[1:], ff.WithEnvVars()); err != nil {
		fmt.Fprintf(os.Stderr, "error: %v\n", err)
		os.Exit(1)
	}

	fmt.Printf("port %d, debug %v\n", *port, *debug)
}
$ env PORT=9090 myservice
port 9090, debug false
$ env PORT=9090 DEBUG=1 myservice -port=1234
port 1234, debug true

Error handling

In general, you should call flag.NewFlagSet with the flag.ContinueOnError error handling strategy, which, somewhat confusingly, is the only way that ff.Parse can return errors. (The other strategies terminate the program on error. Rude!) This is the only way to detect certain types of parse failures, in addition to being good practice in general.

More Repositories

1

diskv

A disk-backed key-value store.
Go
1,401
star
2

go-microservices

Go microservices workshop example project
Go
360
star
3

caspaxos

A Go implementation of the CASPaxos protocol
Go
293
star
4

raft

An implementation of the Raft distributed consensus protocol.
Go
172
star
5

g2s

Get to Statsd: forward simple statistics to a statsd server
Go
149
star
6

how-i-start-go

How I Start: Go
Go
143
star
7

trc

In-process request tracing
Go
93
star
8

mergemap

Go library to recursively merge JSON maps
Go
93
star
9

unixtransport

Support for Unix domain sockets in Go HTTP clients
Go
79
star
10

ctxdata

A helper for collecting and emitting metadata throughout a request lifecycle.
Go
75
star
11

g2g

Get to Graphite: publish Go expvars to a Graphite server
Go
72
star
12

grender

A different take on a static site generator
Go
59
star
13

goop

An audio synthesizer in Go
Go
57
star
14

prometheus-aggregator

Prometheus metrics aggregator
Go
42
star
15

runsvinit

A Docker init process for graceful shutdown of runit services.
Go
39
star
16

gattaca

A monolith and microservices example repository
Go
39
star
17

go-training

Exercises
Go
38
star
18

conntrack

Track incoming and outgoing connections
Go
32
star
19

elasticsearch

ElasticSearch client library for Go
Go
30
star
20

infrastructure

My servers, let me show you them
Shell
26
star
21

sshttp

SSH/HTTP demuxing and proxying server
Go
25
star
22

ps

Publish/subscribe utility
Go
23
star
23

lightctl

Control program for IKEA TRÃ…DFRI smart lights
Go
19
star
24

wtf

Demonstrates a serious problem in the implementation of Go vendoring
Go
19
star
25

breakfast-solutions

A dumb service to illustrate principles of observability
Go
19
star
26

sympatico

Deprecated, please refer to peterbourgon/gattaca
17
star
27

dotfiles

🌀
Shell
15
star
28

ctxlog

Create wide log events in Go programs
Go
15
star
29

ffcli

A minimal package for building flags-first command line interfaces
12
star
30

http-proxy

An HTTP server with a simple config format that proxies to localhost
Go
11
star
31

stats

Compute normal stats on numbers from stdin.
Go
11
star
32

lpg

Local Prometheus and Grafana: work with metrics during development
Makefile
9
star
33

reference

Go kit reference service
Go
8
star
34

srvproxy

Proxy for DNS SRV records
Go
7
star
35

peter-bourgon-org

My web site.
HTML
4
star
36

numberstation

Emit data for websocket listeners
Go
4
star
37

hose-poet

Consume from the firehose; unearth accidental prose
C
4
star
38

tns

Dockertime
Go
3
star
39

crc32

Generate crc32 checksums of data
Go
2
star
40

usage

Nicer help text for Go programs
Go
2
star
41

grid

Controller software for the Monome Grid 128
Go
2
star
42

squawkbox

Squawk!
Go
1
star
43

sums

Does sums
Go
1
star
44

moduledemo

blah
Go
1
star
45

dummyrelease

Go
1
star
46

thirtyfour.org

Hypertext products
Go
1
star