Home

Awesome

Go Reference Go Report Card GitHub Release

cli

Reduce boiler plate needed on each new Golang main functions (Command Line Interface) for both tools and servers (use fortio.org/scli ServerMain() for server)

It abstracts the repetitive parts of a main() command line tool, flag parsing, usage, etc...

You can see real use example in a tool like multicurl or a server like proxy.

It also supports (sub)commands style (where there is a word/command before the flags and remaining arguments, fortio uses that mode).

Tool Example

Client/Tool example (no dynamic flag url or config) sampleTool

Code as simple as

import (
	"flag"
	"os"

	"fortio.org/cli"
	"fortio.org/log"
)

func main() {
	myFlag := flag.String("myflag", "default", "my flag")
	cli.MinArgs = 2
	cli.MaxArgs = 4
	cli.Main() // Will have either called cli.ExitFunction or everything is valid
	// Next line output won't show when passed -quiet
	log.Infof("Info test, -myflag is %q", *myFlag)
	// This always shows
	log.Printf("Hello world, version %s, args %v", cli.ShortVersion, flag.Args())
	// This shows and is colorized and structured, unless loglevel is set to critical.
	log.S(log.Error, "Error test",
		log.Str("myflag", *myFlag),
		log.Attr("num_args", len(flag.Args())),
		log.Attr("args", flag.Args()))
}
$ sampleTool a
sampleTool 1.2.0 usage:
	sampleTool [flags] arg1 arg2 [arg3...arg4]
or 1 of the special arguments
	sampleTool {help|version|buildinfo}
flags:
  -logger-force-color
    	Force color output even if stderr isn't a terminal
  -logger-no-color
    	Prevent colorized output even if stderr is a terminal
  -loglevel level
    	log level, one of [Debug Verbose Info Warning Error Critical Fatal] (default Info)
  -myflag string
    	my flag (default "default")
  -quiet
    	Quiet mode, sets loglevel to Error (quietly) to reduces the output
At least 2 arguments expected, got 1

Since v1.3, the above is colorized on a terminal and looks like this:

Color usage output

or normal case:

Color log output

Old style, no colors:

$ sampleTool -logger-no-color a b
17:20:41 [I] Info test, -myflag is "default"
17:20:41 Hello world, version dev, args [a b]
17:20:41 [E] Error test, myflag="default", num_args="2", args="[a b]"

Additional builtins

buildinfo

e.g

% go install github.com/fortio/multicurl@latest
go: downloading github.com/fortio/multicurl v1.10.1
% multicurl buildinfo
1.10.1 h1:h9yM3XplwG7JWtVaSS0eJPiDmCJfnxvj3w+yoAMWMo4= go1.19.6 arm64 darwin
go	go1.19.6
path	github.com/fortio/multicurl
mod	github.com/fortio/multicurl	v1.10.1	h1:h9yM3XplwG7JWtVaSS0eJPiDmCJfnxvj3w+yoAMWMo4=
dep	fortio.org/cli	v0.6.1	h1:V9L6ly4oz4fJjeQ5745FulIMsFAwFZvLPSUN+cKUrKk=
dep	fortio.org/log	v1.2.2	h1:vs42JjNwiqbMbacittZjJE9+oi72Za6aekML9gKmILg=
dep	fortio.org/version	v1.0.2	h1:8NwxdX58aoeKx7T5xAPO0xlUu1Hpk42nRz5s6e6eKZ0=
build	-compiler=gc
build	CGO_ENABLED=1
build	CGO_CFLAGS=
build	CGO_CPPFLAGS=
build	CGO_CXXFLAGS=
build	CGO_LDFLAGS=
build	GOARCH=arm64
build	GOOS=darwin

help

% multicurl help
Fortio multicurl 1.10.1 usage:
	multicurl [flags] url
or 1 of the special arguments
	multicurl {help|version|buildinfo}
flags:
[...]
  -logger-force-color
    	Force color output even if stderr isn't a terminal
  -logger-no-color
    	Prevent colorized output even if stderr is a terminal
  -loglevel level
    	log level, one of [Debug Verbose Info Warning Error Critical Fatal] (default Info)
  -quiet
    	Quiet mode, sets loglevel to Error (quietly) to reduces the output

version

Short 'numeric' version (v skipped, useful for docker image tags etc)

 % multicurl version
1.10.1

https/tls in FROM scratch docker images

You should always try to use FROM scratch Docker images when possible, it's one of the strength of go.

Using this fortio.org/cli as a base makes it work for outcalls to internet valid TLS certs (e.g. https). It does this by defaulting to the bundle provided by golang.org/x/crypto/x509roots/fallback automatically.

See https://github.com/fortio/multicurl for a good example.

If you do not want this behavior, build using -tags no_tls_fallback.

Small binaries

If you application doesn't do http request/response logging at all, use -tags no_http or -tags no_net (that one will also imply no_tls_fallback) and save 1.6 Mbytes in your binary's size (because the linker isn't smart enough to see net/http isn't actually used) (1.1Mbytes for log's no_http and 530k from the no_tls_fallback)

And, if you don't need any of the advanced JSON logging (which is quite likely with a cli), use -tags no_json the logger will still produce json structured logging just not as advanced if what you log are deep structures - this saves another 130k or so.

These tags are from fortio.org/log v1.14 and later

In summary: for smallest pure local cli binaries using this package:

CGO_ENABLE=0 go build -trimpath -ldflags="-w -s" -tags no_net,no_json .

saves ~1.7Mbytes in total (a basic cli dependending on this package will then only be about 300k more as an hello world yet include color help, buildinfo, version, logging etc)