Like the standard fmt package, but placeholders are named (%<key>verb) instead of positional (%s, %d, …). Values come from a map[string]interface{} or any struct (or other type) that mapstructure can decode into a map.
Install
go get github.com/eslider/format@latest
Documentation for released versions is on pkg.go.dev. New tags are picked up from the module mirror; if a version is missing, request it once (for example go get github.com/eslider/format@v0.1.0) as described in Adding a package.
Usage
Put the name between % and the rest of the verb, for example %<name>s or %<count>d.
Naming rule
Names may use letters, digits, and _ (pattern: [a-zA-Z0-9_]+).
Examples
Import:
import "github.com/eslider/format"
Map: strings
params := map[string]interface{}{
"sister": "Susan",
"brother": "Louis",
}
format.Printf("%<brother>s loves %<sister>s.\n", params)
// Louis loves Susan.
Map: reuse the same key
params := map[string]interface{}{
"sister": "Susan",
"brother": "Louis",
}
s := format.Sprintf(
"%<brother>s loves %<sister>s. %<sister>s also loves %<brother>s.",
params,
)
// Louis loves Susan. Susan also loves Louis.
Map: mixed types (string, int, float)
params := map[string]interface{}{
"user": "Ada",
"score": 42,
"rating": 9.87,
}
msg := format.Sprintf("%<user>s scored %<score>d (avg %<rating>.2f).", params)
// Ada scored 42 (avg 9.87).
Map: floats with width / precision
Named segments keep whatever follows the closing > (same as fmt), so precision works:
params := map[string]interface{}{
"pi": 3.14159265,
"pi_short": 3.14159265,
}
s := format.Sprintf("full %<pi>f, short %<pi_short>.2f", params)
// full 3.141593, short 3.14
Struct: field names as keys
Exported struct fields are matched by name (via mapstructure). Field names in the pattern must match those keys (case-sensitive):
type Person struct {
Brother string
Sister string
}
p := Person{Brother: "Louis", Sister: "Susan"}
line := format.Sprintf("%<Brother>s and %<Sister>s.", p)
// Louis and Susan.
Struct: same template, different rows
Useful for log lines or CSV-like strings without building intermediate slices for fmt:
type Row struct {
ID int
Status string
LatMS float64
}
for _, row := range []Row{
{1, "ok", 12.3},
{2, "retry", 480.99},
} {
format.Printfln("%<ID>05d %<Status>-8s %<LatMS>.1fms", row)
}
// 00001 ok 12.3ms
// 00002 retry 481.0ms
Printfln and Sprintfln
params := map[string]interface{}{"what": "named printf"}
format.Printfln("hello %<what>s", params)
// writes to stdout with trailing newline
s := format.Sprintfln("line: %<what>s", params)
// same string as Sprintf(...) + "\n"
Available methods
| Function |
Behavior |
Printf |
Named format, writes to standard output. |
Printfln |
Like Printf plus newline. |
Sprintf |
Returns formatted string. |
Sprintfln |
Like Sprintf plus \n. |
License
MIT