About tblfmt
September 22, 2026 · View on GitHub
Package tblfmt provides streaming table encoders for result sets (ie, from a
database), creating tables like the following:
author_id | name | z
-----------+-----------------------+---
14 | a b c d |
15 | aoeu +|
| test +|
| |
16 | foo\bbar |
17 | a b \r +|
| a |
18 | 袈 袈 袈 |
19 | 袈 袈 袈+| a+
| |
(6 rows)
Additionally, there are standard encoders for JSON, CSV, HTML, unaligned and
other display variants supported by usql.
Installing
Install in the usual Go fashion:
$ go get -u github.com/xo/tblfmt
Using
tblfmt was designed for use by usql and Go's native database/sql
types, but will handle any type with the following interface:
// ResultSet is the shared interface for a result set.
type ResultSet interface {
Next() bool
Scan(...interface{}) error
Columns() ([]string, error)
Close() error
Err() error
NextResultSet() bool
}
tblfmt can be used similar to the following:
// _example/example.go
package main
import (
"log"
"os"
_ "github.com/lib/pq"
"github.com/xo/dburl"
"github.com/xo/tblfmt"
)
func main() {
db, err := dburl.Open("postgres://booktest:booktest@localhost")
if err != nil {
log.Fatal(err)
}
defer db.Close()
res, err := db.Query("select * from authors")
if err != nil {
log.Fatal(err)
}
defer res.Close()
enc, err := tblfmt.NewTableEncoder(
res,
// force minimum column widths
tblfmt.WithWidths(20, 20),
)
if err = enc.EncodeAll(os.Stdout); err != nil {
log.Fatal(err)
}
}
Which can produce output like the following:
╔══════════════════════╦═══════════════════════════╦═══╗
║ author_id ║ name ║ z ║
╠══════════════════════╬═══════════════════════════╬═══╣
║ 14 ║ a b c d ║ ║
║ 15 ║ aoeu ↵║ ║
║ ║ test ↵║ ║
║ ║ ║ ║
║ 2 ║ 袈 袈 袈 ║ ║
╚══════════════════════╩═══════════════════════════╩═══╝
(3 rows)
Please see the Go Reference for the full API.
Differences from psql
tblfmt follows psql's output closely. The differences below are deliberate;
anything else is a bug worth reporting.
Trailing space on the last column
tblfmt pads the last column of a bordered table, so that every line of a
table is the same width. psql pads the header but trims the data rows,
leaving them ragged.
For select 42 as n, 'a'::text as t union all select 7, 'bb';, with trailing
spaces written as · and the width of each line at the right:
psql 18.6 tblfmt
n | t · 9 n | t · 9
----+---- 9 ----+---- 9
42 | a 7 42 | a · 9
7 | bb 8 7 | bb · 9
psql is wrong here. A table whose lines do not share a width is awkward to
select from a terminal, to diff, and to lay out in anything that measures the
block, and the ragged edge carries no information. It is also inconsistent with
psql's own header, which is padded. tblfmt will not follow it.
Testing
Run using standard go test:
$ go test -v