Name
go-log — Public documentation for gomatic/go-log — a CLI-agnostic log/slog configuration layer for Go.
go-log is the gomatic ecosystem’s CLI-agnostic structured-logging configuration layer for Go. It is a thin layer over the standard library’s log/slog: textual Level and Format value types that bind cleanly from a consumer’s flags, gathered into a LoggerConfig whose NewLogger method builds a *slog.Logger over any io.Writer. The package knows nothing about command-line frameworks — wiring these types to flags lives entirely in the consumer.
- Source:
gomatic/go-log - API reference: pkg.go.dev/github.com/gomatic/go-log
Install
go get github.com/gomatic/go-logWhy a configuration layer
Every CLI needs to turn a --log-level and --log-format flag into a configured *slog.Logger, and every CLI tends to reinvent that plumbing slightly differently. go-log owns the mechanism only: it parses textual levels and formats into the right slog handler, with sensible defaults, and leaves flag declaration to the consumer. The Level and Format types are plain string newtypes, so binding them to a flag is just assigning a string.
Usage
Build a logger
package main
import (
"os"
log "github.com/gomatic/go-log"
)
func main() {
logger := log.LoggerConfig{Level: "info", Format: log.FormatJSON}.NewLogger(os.Stderr)
logger.Info("ready", "addr", ":8080")
}LoggerConfig is a value, not a pointer — copy it freely. NewLogger accepts any io.Writer, so the same config drives a logger to os.Stderr, a file, or a test buffer.
Levels
Level accepts debug, info, warn, or error, and defaults to info when the value is empty or unrecognized:
log.LoggerConfig{Level: "debug"}.NewLogger(os.Stderr) // debug and above
log.LoggerConfig{Level: ""}.NewLogger(os.Stderr) // empty → info
log.LoggerConfig{Level: "bogus"}.NewLogger(os.Stderr) // invalid → infoFormats
Format selects the encoding via the two exported constants, and defaults to text for any unknown value:
log.LoggerConfig{Format: log.FormatText}.NewLogger(os.Stderr) // text handler
log.LoggerConfig{Format: log.FormatJSON}.NewLogger(os.Stderr) // json handler
log.LoggerConfig{Format: "yaml"}.NewLogger(os.Stderr) // unknown → textBinding to flags
The point of the string newtypes is that a consumer binds them straight from its own flag layer — go-log never imports a CLI framework:
cfg := log.LoggerConfig{
Level: log.Level(*levelFlag), // e.g. "warn"
Format: log.Format(*formatFlag), // e.g. "json"
}
logger := cfg.NewLogger(os.Stderr)Design
- Two textual value types —
LevelandFormatarestringnewtypes, so they are safe to copy, compare, and assign directly from a flag’s string value. - Forgiving defaults — an empty or invalid
Levelresolves toinfo; an unknownFormatresolves to the text handler. A misconfigured flag degrades to a working logger rather than failing. - Any writer —
NewLoggertakes anio.Writer, decoupling the logger fromos.Stderrand making it trivial to capture output in tests. - CLI-agnostic — the package depends only on the standard library (
io,log/slog) and knows nothing about command-line frameworks; flag binding lives in the consumer.
Who uses it
Every gomatic Go CLI shares this logging setup rather than re-deriving it: renderizer, template.cli, and the other gomatic/go-* libraries.