The github.com/olekukonko/tablewriter/renderer package provides multiple rendering engines for generating tables in different output formats. Each renderer implements the tw.Renderer interface and supports features like borders, alignment, cell merging, and customizable styling.
go get github.com/olekukonko/tablewriter@v1.1.2import (
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
)The package provides six rendering engines, each optimized for different output formats:
The Blueprint renderer is the primary ASCII/Unicode table rendering engine with full support for borders, alignments, padding, and cell merging.
func NewBlueprint(configs ...tw.Rendition) *BlueprintCreates a Blueprint renderer with optional rendition configuration.
Parameters:
configs ...tw.Rendition - Optional rendition configurations (only first is used)Returns:
*Blueprint - Blueprint renderer instancefunc (f *Blueprint) Start(w io.Writer) error
func (f *Blueprint) Header(headers [][]string, ctx tw.Formatting)
func (f *Blueprint) Row(row []string, ctx tw.Formatting)
func (f *Blueprint) Footer(footers [][]string, ctx tw.Formatting)
func (f *Blueprint) Line(ctx tw.Formatting)
func (f *Blueprint) Config() tw.Rendition
func (f *Blueprint) Close() error
func (f *Blueprint) Logger(logger *ll.Logger)
func (f *Blueprint) Rendition(config tw.Rendition)Method Descriptions:
Start - Initializes rendering with output writerHeader - Renders table header sectionRow - Renders data rowFooter - Renders table footer sectionLine - Renders separator line with junctionsConfig - Returns current rendition configurationClose - Finalizes rendering and cleanupLogger - Sets logger instance for debug messagesRendition - Updates rendition configuration dynamicallyimport (
"os"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
)
// Create Blueprint renderer with custom configuration
rendition := tw.Rendition{
Borders: tw.Border{
Left: tw.On,
Right: tw.On,
Top: tw.On,
Bottom: tw.On,
},
Symbols: tw.NewSymbols(tw.StyleLight),
Settings: tw.Settings{
Separators: tw.Separators{
BetweenColumns: tw.On,
BetweenRows: tw.Off,
},
},
}
blueprint := renderer.NewBlueprint(rendition)
blueprint.Start(os.Stdout)
// Render table content
ctx := tw.Formatting{
Row: tw.RowContext{
Position: tw.Header,
Location: tw.LocationFirst,
Current: map[int]tw.CellContext{
0: {Data: "Name", Align: tw.AlignCenter, Width: 20},
1: {Data: "Age", Align: tw.AlignCenter, Width: 10},
},
Widths: tw.NewMapper[int, int]().Set(0, 20).Set(1, 10),
},
}
blueprint.Header([][]string{{"Name", "Age"}}, ctx)
blueprint.Close()The Colorized renderer generates ASCII tables with ANSI color support for terminal output.
func NewColorized(configs ...ColorizedConfig) *ColorizedCreates a Colorized renderer with optional color configuration.
Parameters:
configs ...ColorizedConfig - Optional color configurations (only first is used)Returns:
*Colorized - Colorized renderer instancetype ColorizedConfig struct {
Borders tw.Border // Border visibility settings
Settings tw.Settings // Rendering behavior settings
Header Tint // Colors for header cells
Column Tint // Colors for row cells
Footer Tint // Colors for footer cells
Border Tint // Colors for borders and lines
Separator Tint // Colors for column separators
Symbols tw.Symbols // Symbols for table drawing
}Fields:
Borders - Border visibility (Left, Right, Top, Bottom)Settings - Separators, lines, and compact mode settingsHeader - Header text and background colorsColumn - Row text and background colorsFooter - Footer text and background colorsBorder - Border line colorsSeparator - Column separator colorsSymbols - Border symbol set (corners, lines, junctions)type Tint struct {
FG Colors // Foreground color attributes
BG Colors // Background color attributes
Columns []Tint // Per-column color settings
}Fields:
FG - Foreground color attributes (text color)BG - Background color attributes (cell background)Columns - Per-column color overridesMethods:
func (t Tint) Apply(text string) stringApplies the tint's colors to text, returning unchanged text if no colors are set.
type Colors []color.AttributeA slice of color attributes from the github.com/fatih/color package (e.g., color.FgWhite, color.Bold).
func (c *Colorized) Start(w io.Writer) error
func (c *Colorized) Header(headers [][]string, ctx tw.Formatting)
func (c *Colorized) Row(row []string, ctx tw.Formatting)
func (c *Colorized) Footer(footers [][]string, ctx tw.Formatting)
func (c *Colorized) Line(ctx tw.Formatting)
func (c *Colorized) Config() tw.Rendition
func (c *Colorized) Close() error
func (c *Colorized) Logger(logger *ll.Logger)
func (c *Colorized) Reset()
func (c *Colorized) Rendition(config tw.Rendition)
func (c *Colorized) Debug() []stringMethod Descriptions:
Start - Initializes rendering with output writerHeader - Renders colored header sectionRow - Renders colored data rowFooter - Renders colored footer sectionLine - Renders colored separator lineConfig - Returns current rendition configurationClose - Finalizes renderingLogger - Sets logger instanceReset - Clears internal state including debug tracesRendition - Updates rendition configurationDebug - Returns accumulated debug trace messagesimport (
"os"
"github.com/fatih/color"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
)
// Create Colorized renderer with color configuration
config := renderer.ColorizedConfig{
Header: renderer.Tint{
FG: renderer.Colors{color.FgWhite},
BG: renderer.Colors{color.BgBlue},
},
Column: renderer.Tint{
FG: renderer.Colors{color.FgBlack},
BG: renderer.Colors{color.BgWhite},
},
Border: renderer.Tint{
FG: renderer.Colors{color.FgCyan},
},
Separator: renderer.Tint{
FG: renderer.Colors{color.FgGreen},
},
Symbols: tw.NewSymbols(tw.StyleLight),
}
colorized := renderer.NewColorized(config)
colorized.Start(os.Stdout)
// Render colored table
ctx := tw.Formatting{
Row: tw.RowContext{
Position: tw.Header,
Current: map[int]tw.CellContext{
0: {Data: "Product", Align: tw.AlignLeft, Width: 30},
1: {Data: "Price", Align: tw.AlignRight, Width: 15},
},
Widths: tw.NewMapper[int, int]().Set(0, 30).Set(1, 15),
},
}
colorized.Header([][]string{{"Product", "Price"}}, ctx)
colorized.Close()The HTML renderer generates HTML tables with customizable CSS classes and support for cell merging.
func NewHTML(configs ...HTMLConfig) *HTMLCreates an HTML renderer with optional configuration.
Parameters:
configs ...HTMLConfig - Optional HTML configurations (only first is used)Returns:
*HTML - HTML renderer instancetype HTMLConfig struct {
EscapeContent bool // Whether to escape cell content
AddLinesTag bool // Whether to wrap multiline content in <lines> tags
TableClass string // CSS class for <table>
HeaderClass string // CSS class for <thead>
BodyClass string // CSS class for <tbody>
FooterClass string // CSS class for <tfoot>
RowClass string // CSS class for <tr> in body
HeaderRowClass string // CSS class for <tr> in header
FooterRowClass string // CSS class for <tr> in footer
}Fields:
EscapeContent - Escapes HTML special characters (default: true)AddLinesTag - Wraps multiline content in <lines> tags (default: false)TableClass - CSS class for <table> elementHeaderClass - CSS class for <thead> elementBodyClass - CSS class for <tbody> elementFooterClass - CSS class for <tfoot> elementRowClass - CSS class for <tr> elements in bodyHeaderRowClass - CSS class for <tr> elements in headerFooterRowClass - CSS class for <tr> elements in footerfunc (h *HTML) Start(w io.Writer) error
func (h *HTML) Header(headers [][]string, ctx tw.Formatting)
func (h *HTML) Row(row []string, ctx tw.Formatting)
func (h *HTML) Footer(footers [][]string, ctx tw.Formatting)
func (h *HTML) Line(ctx tw.Formatting)
func (h *HTML) Config() tw.Rendition
func (h *HTML) Close() error
func (h *HTML) Logger(logger *ll.Logger)
func (h *HTML) Reset()
func (h *HTML) Debug() []stringMethod Descriptions:
Start - Opens <table> tag and initializes renderingHeader - Renders <thead> section with header rowsRow - Renders <tr> in <tbody> sectionFooter - Renders <tfoot> section with footer rowsLine - No-op (structural lines handled by HTML tags)Config - Returns current configurationClose - Closes all open tags and finalizes HTMLLogger - Sets logger instanceReset - Clears internal state and merge trackingDebug - Returns accumulated debug trace messagesimport (
"os"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
)
// Create HTML renderer with CSS classes
config := renderer.HTMLConfig{
EscapeContent: true,
TableClass: "data-table",
HeaderClass: "table-header",
BodyClass: "table-body",
RowClass: "table-row",
HeaderRowClass: "header-row",
}
html := renderer.NewHTML(config)
html.Start(os.Stdout)
// Render HTML table
ctx := tw.Formatting{
Row: tw.RowContext{
Position: tw.Header,
Current: map[int]tw.CellContext{
0: {Data: "ID", Align: tw.AlignCenter},
1: {Data: "Name", Align: tw.AlignLeft},
2: {Data: "Status", Align: tw.AlignCenter},
},
},
}
html.Header([][]string{{"ID", "Name", "Status"}}, ctx)
// Render row with horizontal merge
rowCtx := tw.Formatting{
Row: tw.RowContext{
Position: tw.Row,
Current: map[int]tw.CellContext{
0: {Data: "1", Align: tw.AlignCenter},
1: {
Data: "Merged Cell",
Align: tw.AlignLeft,
Merge: tw.MergeState{
Horizontal: tw.MergeStateOption{
Present: true,
Start: true,
Span: 2,
},
},
},
},
},
}
html.Row([]string{"1", "Merged Cell"}, rowCtx)
html.Close()The Markdown renderer generates GitHub-flavored Markdown tables.
func NewMarkdown(configs ...tw.Rendition) *MarkdownCreates a Markdown renderer with optional configuration.
Parameters:
configs ...tw.Rendition - Optional rendition configurations (only first is used)Returns:
*Markdown - Markdown renderer instancefunc (m *Markdown) Start(w io.Writer) error
func (m *Markdown) Header(headers [][]string, ctx tw.Formatting)
func (m *Markdown) Row(row []string, ctx tw.Formatting)
func (m *Markdown) Footer(footers [][]string, ctx tw.Formatting)
func (m *Markdown) Line(ctx tw.Formatting)
func (m *Markdown) Config() tw.Rendition
func (m *Markdown) Close() error
func (m *Markdown) Logger(logger *ll.Logger)
func (m *Markdown) Reset()Method Descriptions:
Start - Initializes rendering with output writerHeader - Renders Markdown header with alignment separatorRow - Renders Markdown data rowFooter - Renders Markdown footerLine - No-op (only header separator is rendered)Config - Returns current configurationClose - Finalizes renderingLogger - Sets logger instanceReset - Clears internal stateimport (
"os"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
)
// Create Markdown renderer
markdown := renderer.NewMarkdown()
markdown.Start(os.Stdout)
// Render Markdown table
ctx := tw.Formatting{
Row: tw.RowContext{
Position: tw.Header,
Current: map[int]tw.CellContext{
0: {Data: "Column 1", Align: tw.AlignLeft, Width: 20},
1: {Data: "Column 2", Align: tw.AlignCenter, Width: 15},
2: {Data: "Column 3", Align: tw.AlignRight, Width: 15},
},
Widths: tw.NewMapper[int, int]().Set(0, 20).Set(1, 15).Set(2, 15),
},
}
markdown.Header([][]string{{"Column 1", "Column 2", "Column 3"}}, ctx)
// Render data rows
rowCtx := tw.Formatting{
Row: tw.RowContext{
Position: tw.Row,
Current: map[int]tw.CellContext{
0: {Data: "Left", Align: tw.AlignLeft, Width: 20},
1: {Data: "Center", Align: tw.AlignCenter, Width: 15},
2: {Data: "Right", Align: tw.AlignRight, Width: 15},
},
Widths: tw.NewMapper[int, int]().Set(0, 20).Set(1, 15).Set(2, 15),
},
}
markdown.Row([]string{"Left", "Center", "Right"}, rowCtx)
markdown.Close()Output:
| Column 1 | Column 2 | Column 3 |
|:---------------------|:---------------:|----------------:|
| Left | Center | Right |The Ocean renderer is a streaming table renderer optimized for real-time output with fixed column widths.
func NewOcean(oceanConfig ...OceanConfig) *OceanCreates an Ocean renderer with optional configuration.
Parameters:
oceanConfig ...OceanConfig - Optional Ocean configurations (only first is used)Returns:
*Ocean - Ocean renderer instancetype OceanConfig struct{}Ocean renderer configuration (currently empty, reserved for future extensibility).
func (o *Ocean) Start(w io.Writer) error
func (o *Ocean) Header(headers [][]string, ctx tw.Formatting)
func (o *Ocean) Row(row []string, ctx tw.Formatting)
func (o *Ocean) Footer(footers [][]string, ctx tw.Formatting)
func (o *Ocean) Line(ctx tw.Formatting)
func (o *Ocean) Config() tw.Rendition
func (o *Ocean) Close() error
func (o *Ocean) Logger(logger *ll.Logger)
func (o *Ocean) Rendition(config tw.Rendition)Method Descriptions:
Start - Initializes streaming rendererHeader - Renders header lines immediatelyRow - Renders data rows immediatelyFooter - Renders footer lines immediatelyLine - Renders separator lineConfig - Returns current configurationClose - Finalizes rendering and resets stateLogger - Sets logger instanceRendition - Updates rendition configuration dynamicallyimport (
"os"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
)
// Create Ocean renderer for streaming
ocean := renderer.NewOcean()
ocean.Start(os.Stdout)
// Define column widths upfront
widths := tw.NewMapper[int, int]().Set(0, 20).Set(1, 15).Set(2, 10)
// Render header
headerCtx := tw.Formatting{
Row: tw.RowContext{
Position: tw.Header,
Location: tw.LocationFirst,
Widths: widths,
Current: map[int]tw.CellContext{
0: {Data: "Item", Align: tw.AlignLeft},
1: {Data: "Quantity", Align: tw.AlignCenter},
2: {Data: "Price", Align: tw.AlignRight},
},
},
}
ocean.Header([][]string{{"Item", "Quantity", "Price"}}, headerCtx)
// Stream rows as they become available
for _, item := range items {
rowCtx := tw.Formatting{
Row: tw.RowContext{
Position: tw.Row,
Widths: widths,
Current: map[int]tw.CellContext{
0: {Data: item.Name, Align: tw.AlignLeft},
1: {Data: fmt.Sprintf("%d", item.Qty), Align: tw.AlignCenter},
2: {Data: fmt.Sprintf("$%.2f", item.Price), Align: tw.AlignRight},
},
},
}
ocean.Row([]string{item.Name, fmt.Sprintf("%d", item.Qty), fmt.Sprintf("$%.2f", item.Price)}, rowCtx)
}
ocean.Close()The SVG renderer generates scalable vector graphics tables with customizable fonts, colors, and styling.
func NewSVG(configs ...SVGConfig) *SVGCreates an SVG renderer with optional configuration.
Parameters:
configs ...SVGConfig - Optional SVG configurations (only first is used)Returns:
*SVG - SVG renderer instancetype SVGConfig struct {
FontFamily string // Font family (e.g., "Arial, sans-serif")
FontSize float64 // Base font size in SVG units (default: 12.0)
LineHeightFactor float64 // Line height multiplier (default: 1.4)
Padding float64 // Cell padding in points (default: 5.0)
StrokeWidth float64 // Border line width (default: 1.0)
StrokeColor string // Border color (default: "black")
HeaderBG string // Header background color (default: "#F0F0F0")
RowBG string // Row background color (default: "white")
RowAltBG string // Alternate row background (default: "#F9F9F9")
FooterBG string // Footer background color (default: "#E0E0E0")
HeaderColor string // Header text color (default: "black")
RowColor string // Row text color (default: "black")
FooterColor string // Footer text color (default: "black")
ApproxCharWidthFactor float64 // Character width estimation factor (default: 0.6)
MinColWidth float64 // Minimum column width (default: 30.0)
RenderTWConfigOverrides bool // Use tablewriter config for alignments (default: true)
Debug bool // Enable debug logging (default: false)
ScaleFactor float64 // SVG scaling factor (default: 1.0)
}Fields:
FontFamily - Font family for text renderingFontSize - Base font size in SVG unitsLineHeightFactor - Multiplier for line height calculationPadding - Internal cell paddingStrokeWidth - Width of border linesStrokeColor - Color for borders and linesHeaderBG - Background color for header cellsRowBG - Background color for data row cellsRowAltBG - Background color for alternating rowsFooterBG - Background color for footer cellsHeaderColor - Text color for headerRowColor - Text color for data rowsFooterColor - Text color for footerApproxCharWidthFactor - Character width relative to font sizeMinColWidth - Minimum width for columnsRenderTWConfigOverrides - Whether to use tablewriter alignmentsDebug - Enable debug loggingScaleFactor - Scaling factor for entire SVGfunc (s *SVG) Start(w io.Writer) error
func (s *SVG) Header(headers [][]string, ctx tw.Formatting)
func (s *SVG) Row(row []string, ctx tw.Formatting)
func (s *SVG) Footer(footers [][]string, ctx tw.Formatting)
func (s *SVG) Line(ctx tw.Formatting)
func (s *SVG) Config() tw.Rendition
func (s *SVG) Close() error
func (s *SVG) Logger(logger *ll.Logger)
func (s *SVG) Reset()
func (s *SVG) Debug() []stringMethod Descriptions:
Start - Initializes SVG rendering and resets stateHeader - Buffers header lines for renderingRow - Buffers data row for renderingFooter - Buffers footer lines for renderingLine - Ignored (borders drawn in Close)Config - Returns current configurationClose - Finalizes SVG and writes complete outputLogger - Sets logger instanceReset - Clears buffered data and internal stateDebug - Returns debug trace messagesimport (
"os"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
)
// Create SVG renderer with custom styling
config := renderer.SVGConfig{
FontFamily: "Arial, sans-serif",
FontSize: 14.0,
Padding: 8.0,
StrokeWidth: 2.0,
StrokeColor: "#333333",
HeaderBG: "#4A90E2",
HeaderColor: "white",
RowBG: "#FFFFFF",
RowAltBG: "#F5F5F5",
RowColor: "#333333",
}
svg := renderer.NewSVG(config)
svg.Start(os.Stdout)
// Render SVG table
headerCtx := tw.Formatting{
Row: tw.RowContext{
Position: tw.Header,
Current: map[int]tw.CellContext{
0: {Data: "Employee", Align: tw.AlignLeft},
1: {Data: "Department", Align: tw.AlignCenter},
2: {Data: "Salary", Align: tw.AlignRight},
},
},
}
svg.Header([][]string{{"Employee", "Department", "Salary"}}, headerCtx)
// Add data rows
rowCtx := tw.Formatting{
Row: tw.RowContext{
Position: tw.Row,
Current: map[int]tw.CellContext{
0: {Data: "John Doe", Align: tw.AlignLeft},
1: {Data: "Engineering", Align: tw.AlignCenter},
2: {Data: "$120,000", Align: tw.AlignRight},
},
},
}
svg.Row([]string{"John Doe", "Engineering", "$120,000"}, rowCtx)
svg.Close()The Junction type helps with rendering table junction points (corners and intersections) with color support.
func NewJunction(ctx JunctionContext) *JunctionCreates a Junction renderer with the given context.
Parameters:
ctx JunctionContext - Junction rendering contextReturns:
*Junction - Junction renderer instancetype JunctionContext struct {
Symbols tw.Symbols // Border symbol set
Ctx tw.Formatting // Formatting context
ColIdx int // Column index
Logger *ll.Logger // Logger instance
BorderTint Tint // Border color tint
SeparatorTint Tint // Separator color tint
}Fields:
Symbols - Symbol set for drawing junctionsCtx - Current formatting context (position, location, merge states)ColIdx - Current column index being processedLogger - Logger for debug messagesBorderTint - Color tint for border symbolsSeparatorTint - Color tint for separator symbolsThe Junction type provides internal methods used by renderers:
GetSegment() - Returns horizontal line segment or empty space based on merge statesRenderLeft() - Returns colored left border junction symbolRenderRight(lastColIdx int) - Returns colored right border junction symbolRenderJunction(leftColIdx, rightColIdx int) - Returns colored junction between columnsThese methods are typically used internally by Blueprint and Colorized renderers and handle complex logic for determining appropriate junction symbols based on table structure, cell merges, and current position.
All renderers implement the tw.Renderer interface:
type Renderer interface {
Start(w io.Writer) error
Header(headers [][]string, ctx tw.Formatting)
Row(row []string, ctx tw.Formatting)
Footer(footers [][]string, ctx tw.Formatting)
Line(ctx tw.Formatting)
Config() tw.Rendition
Close() error
Logger(logger *ll.Logger)
}Choose the appropriate renderer based on your output requirements:
| Renderer | Use Case | Features |
|---|---|---|
| Blueprint | Terminal output, text files | Full border control, all merge types, customizable symbols |
| Colorized | Terminal with color support | ANSI colors, per-cell/column/row tinting, color borders |
| HTML | Web pages, HTML reports | CSS classes, colspan/rowspan, content escaping |
| Markdown | Documentation, READMEs | GitHub-flavored tables, alignment indicators |
| Ocean | Streaming output, large tables | Fixed-width streaming, immediate output |
| SVG | Scalable graphics, PDFs | Vector graphics, custom fonts, precise styling |
All renderers support horizontal, vertical, and hierarchical cell merging through the tw.MergeState type:
merge := tw.MergeState{
Horizontal: tw.MergeStateOption{
Present: true,
Start: true,
Span: 3, // Merge across 3 columns
},
}Blueprint, Colorized, and Ocean renderers implement tw.Renditioning interface for dynamic configuration updates:
type Renditioning interface {
Rendition(r Rendition)
}This allows updating borders, symbols, and settings during rendering.
Colorized, HTML, and SVG renderers provide debug trace access:
renderer := renderer.NewColorized()
// ... render table ...
traces := renderer.Debug()
for _, trace := range traces {
fmt.Println(trace)
}The renderer package depends on types from the tw package:
tw.Renderer - Core renderer interfacetw.Rendition - Renderer configuration (borders, symbols, settings)tw.Formatting - Row formatting contexttw.RowContext - Row layout and cell propertiestw.CellContext - Individual cell propertiestw.MergeState - Cell merge informationtw.Symbols - Border symbol setstw.Align - Text alignment optionstw.Padding - Cell padding configuration