• Stars
    star
    1,305
  • Rank 34,849 (Top 0.8 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 6 years ago
  • Updated about 2 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,343
star
2

go-microservices

Go microservices workshop example project
Go
354
star
3

caspaxos

A Go implementation of the CASPaxos protocol
Go
294
star
4

raft

An implementation of the Raft distributed consensus protocol.
Go
171
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
142
star
7

mergemap

Go library to recursively merge JSON maps
Go
91
star
8

trc

In-process request tracing
Go
86
star
9

unixtransport

Support for Unix domain sockets in Go HTTP clients
Go
77
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
73
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
41
star
15

gattaca

A monolith and microservices example repository
Go
39
star
16

runsvinit

A Docker init process for graceful shutdown of runit services.
Go
38
star
17

go-training

Exercises
Go
37
star
18

elasticsearch

ElasticSearch client library for Go
Go
30
star
19

conntrack

Track incoming and outgoing connections
Go
27
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

lightctl

Control program for IKEA TRΓ…DFRI smart lights
Go
19
star
23

wtf

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

breakfast-solutions

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

sympatico

Deprecated, please refer to peterbourgon/gattaca
17
star
26

dotfiles

πŸŒ€
Shell
15
star
27

ctxlog

Create wide log events in Go programs
Go
15
star
28

ffcli

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

stats

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

http-proxy

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

lpg

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

reference

Go kit reference service
Go
8
star
33

srvproxy

Proxy for DNS SRV records
Go
6
star
34

peter-bourgon-org

My web site.
HTML
4
star
35

numberstation

Emit data for websocket listeners
Go
4
star
36

hose-poet

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

crc32

Generate crc32 checksums of data
Go
3
star
38

tns

Dockertime
Go
3
star
39

usage

Nicer help text for Go programs
Go
2
star
40

ps

Publish/subscribe utility
Go
2
star
41

squawkbox

Squawk!
Go
1
star
42

sums

Does sums
Go
1
star
43

moduledemo

blah
Go
1
star
44

dummyrelease

Go
1
star
45

grid

Controller software for the Monome Grid 128
Go
1
star
46

thirtyfour.org

Hypertext products
Go
1
star