Hi there! I'm Shrijith Venkatrama, founder of Hexmos. Right now, I’m building LiveAPI, a tool that makes generating API docs from your code ridiculously easy.

PDF generation isn't a one-size-fits-all problem.

Depending on whether you're building simple invoices, complex reports, beautiful exports, or dynamic UIs turned into PDFs, there are several solid approaches you can use in Go.

This article covers the main practical methods with complete examples, pros/cons, and guidance on when to pick what.

Why Generate PDFs in Go?

  • Full backend control — no SaaS dependency.
  • Low latency — avoid extra API hops.
  • Customization — adjust layouts, formats, and security options.
  • Automation — dynamically build content from your services.
Advantage Reason
Privacy No third-party data leaks
Cost savings No per-document fees
Speed Generate on demand

Native Go Libraries for PDF Generation

1. Using gofpdf for Basic PDFs

gofpdf is the classic choice: pure Go, dependency-free.

Example:

package main

import (
    "github.com/jung-kurt/gofpdf"
)

func main() {
    pdf := gofpdf.New("P", "mm", "A4", "")
    pdf.AddPage()
    pdf.SetFont("Arial", "B", 16)
    pdf.Cell(40, 10, "Hello, gofpdf!")
    pdf.OutputFileAndClose("basic_gofpdf.pdf")
}

Output: A simple one-line "Hello" PDF.

Pros Cons
Pure Go Manual layout effort
No external tools needed Limited complex layout support

2. Using unidoc/unipdf for High-End PDFs

unipdf is a commercial-grade library.

It's powerful, feature-rich, and paid for production — but free for personal and trial use.

Example:

package main

import (
    "github.com/unidoc/unipdf/v3/model"
    "log"
    "os"
)

func main() {
    pdf := model.NewPdfWriter()

    f, err := os.Create("unipdf_output.pdf")
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()

    err = pdf.Write(f)
    if err != nil {
        log.Fatal(err)
    }
}

Pros:

  • Vector graphics, annotations, encryption.
  • Table/grid helpers.
  • Commercial support.

Cons:

  • License required for production.

Link: UniPDF Documentation

3. Using pdfcpu for PDF Manipulation

pdfcpu is more focused on editing, processing, and validating PDFs, but it can generate simple PDFs too.

Example:

package main

import (
    "github.com/pdfcpu/pdfcpu/pkg/api"
    "log"
)

func main() {
    err := api.CreateDemoPDF("pdfcpu_demo.pdf", "", nil)
    if err != nil {
        log.Fatal(err)
    }
}

Pros:

  • Splitting, merging, watermarking PDFs.
  • CLI and library mode.

Cons:

  • Not designed for full creative layout generation.

Link: pdfcpu Documentation

Template-Based Generation: Go → LaTeX → PDF

For professional typesetting, LaTeX is still king.

Generate .tex files dynamically in Go, compile using pdflatex.

Example:

package main

import (
    "os"
    "os/exec"
)

func main() {
    content := `\documentclass{article}
\begin{document}
Hello, \textbf{LaTeX} World!
\end{document}`

    os.WriteFile("output.tex", []byte(content), 0644)

    cmd := exec.Command("pdflatex", "output.tex")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    err := cmd.Run()
    if err != nil {
        panic(err)
    }
}
Pros Cons
Stunning typography Requires LaTeX installed
Advanced features (TOC, BibTeX) Learning curve

Link: Quick Start with LaTeX

Markdown + Pandoc: Flexible and Clean

If you like Markdown, you can generate it dynamically and pipe it through Pandoc to create PDFs.

Example:

package main

import (
    "os"
    "os/exec"
)

func main() {
    markdown := `# Auto Report

This report was generated by Go and Pandoc.`

    os.WriteFile("report.md", []byte(markdown), 0644)

    cmd := exec.Command("pandoc", "report.md", "-o", "report.pdf")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    err := cmd.Run()
    if err != nil {
        panic(err)
    }
}
Pros Cons
Easy content authoring Needs Pandoc installed
Good support for tables, links, images Slightly heavier pipeline

Link: Pandoc Markdown Syntax

HTML to PDF: Chrome Headless, wkhtmltopdf

If you already have HTML layouts (e.g., templates, dashboards), rendering HTML into PDF makes perfect sense.

Using Headless Chrome (via chromedp)

chromedp lets you programmatically control Chrome.

Example:

package main

import (
    "context"
    "io/ioutil"
    "log"
    "time"

    "github.com/chromedp/chromedp"
)

func main() {
    ctx, cancel := chromedp.NewContext(context.Background())
    defer cancel()

    var pdfBuf []byte
    err := chromedp.Run(ctx,
        chromedp.Navigate("https://example.com"),
        chromedp.Sleep(2*time.Second), // wait for page load
        chromedp.ActionFunc(func(ctx context.Context) error {
            var err error
            pdfBuf, _, err = page.PrintToPDF().Do(ctx)
            return err
        }),
    )
    if err != nil {
        log.Fatal(err)
    }

    ioutil.WriteFile("chrome_output.pdf", pdfBuf, 0644)
}
Pros Cons
Full CSS, JS, dynamic pages Heavy runtime (Chrome)

Link: chromedp PrintToPDF


Using wkhtmltopdf

wkhtmltopdf is a simpler, mature tool: turn any HTML file into a PDF without needing full Chrome.

Example:

package main

import (
    "os/exec"
    "log"
)

func main() {
    cmd := exec.Command("wkhtmltopdf", "https://example.com", "output.pdf")
    cmd.Stdout = nil
    cmd.Stderr = nil
    err := cmd.Run()
    if err != nil {
        log.Fatal(err)
    }
}
Pros Cons
Lightweight Not always perfect with complex JS

Link: wkhtmltopdf Manual

Quick Comparison of All Methods

Method Best For Needs External Tools? Difficulty
gofpdf Simple static PDFs No Easy
unipdf Complex dynamic documents No (license needed) Medium
pdfcpu PDF processing and editing No Easy
Go → LaTeX → PDF High-quality, complex typesetting Yes (LaTeX) Medium-Hard
Go → Markdown → Pandoc → PDF Lightweight reports, docs Yes (Pandoc) Medium
Headless Chrome Full web page snapshots Yes (Chrome) Medium
wkhtmltopdf Simple HTML to PDF exports Yes Easy-Medium

Choosing the Right Method

Situation Recommended Option
Static invoices, simple docs gofpdf
Long reports, academic documents LaTeX + pdflatex
Blog-like or documentation exports Markdown + Pandoc
HTML dashboard snapshots chromedp or wkhtmltopdf
Need to manipulate existing PDFs pdfcpu
Premium enterprise-grade needs unipdf

Final Thoughts

The right choice depends heavily on your:

  • Required layout complexity
  • Tolerance for installing external tools
  • Performance and runtime footprint

When in doubt, start simple (like gofpdf) and scale complexity only when necessary.