Bounded ZIP Reads
ReadOptions limits archive bytes, uncompressed part size, total declared expansion, and entry count through WithOptions APIs for DOM, template, and streaming readers.
100% pure Go standard library, zero third-party dependencies — an industrial-grade engine for Microsoft Word (.docx) processing.
The reader now restores section geometry and common header/footer parts, notes, comments, revisions, and list numbering. Template replacement handles macros split across adjacent Word text runs. NewWithOptions provides isolated document defaults, and ValidatePackage reports package diagnostics. See Reader & Diagnostics.
ReadOptions and the WithOptions APIs. Existing APIs retain unlimited reads. See limits and a runnable example.See the v0.11.0 release and changelog.
Production Word pipelines usually stall on four constraints: shipping a binary into an air-gapped network, keeping RAM flat on multi-hundred-page extracts, emitting equations Microsoft Word can edit, and filling legal templates without a second templating stack.
| Constraint | GoWord | Typical PHP / Python stack | Other Go .docx writers |
|---|---|---|---|
| Language & deps | Go 1.21+ standard library only | runtime + XML / ZIP extras | often stdlib, write-only surface |
| Extract memory | StreamExtractText O(1) extra heap | load the whole package / DOM | full document tree |
| Equations | LaTeX → native OMML (m:oMathPara) | image, OLE, or omit | omit |
| Templates | ${var | pipe} + ${block} / ${if} | PHPWord macros or Jinja→docx | omit or string replace |
| Merge isolation | AppendDocument remaps styles, bookmarks, rId | ZIP copy, colliding image1.png | omit |
| License | LGPL v3 | mixed | AGPL or MIT write-only |
GoWord keeps the PHPWord names (AddSection, AddText, IOFactory, TemplateProcessor) on a pure-Go OpenXML writer. Four copy-paste programs that combine these advantages live under Enterprise Recipes.
Numbers from go test -benchmem on Intel Core i7-10870H, Windows amd64. Allocations are the stable signal; wall time moves with disk and CPU. Full tables, hardware notes, and a streaming-extract occupancy example: Benchmarks.
| Workload | ns/op | B/op | allocs/op |
|---|---|---|---|
BenchmarkSaveDocx — 30 paragraphs + 20×5 table | 1.88e6 | 163 KiB | 949 |
BenchmarkTableRender — 50×8 table | 2.76e6 | 180 KiB | 1820 |
BenchmarkTemplateProcess — two ${} replacements | 1.43e6 | 238 KiB | 703 |
BenchmarkStreamWriter — incremental ZIP | 1.55e6 | 142 KiB | 627 |
B/op is extra heap per iteration, not the size of the .docx. Stream extract discards each paragraph buffer after the callback, so extra memory stays O(1) relative to file size.
GoWord ports the PHPWord public API (AddSection, AddText, IOFactory, TemplateProcessor) onto a pure-Go OpenXML writer. The table below compares the surface that production Word pipelines usually need.
| Capability | GoWord | PHPWord | unioffice | fumiama/go-docx | gingfrederik/docx |
|---|---|---|---|---|---|
| Language | Go 1.21+ | PHP | Go (commercial) | Go | Go |
| License | LGPL v3 | LGPL v3 | Commercial | AGPL-3.0 | MIT |
| Third-party Go deps | None | n/a | None (paid SDK) | None | None |
Create .docx | ✓ | ✓ | ✓ | ✓ | ✓ |
Read / round-trip .docx | ✓ | ✓ | ✓ | ✓ | |
| Native OMML from LaTeX | ✓ | ✓ | |||
| DrawingML charts (bar / line / pie / area / combo) | ✓ | ✓ | ✓ | ||
Vector shapes wps:wsp | ✓ | ✓ | ✓ | ✓ | |
Multi-column w:cols | ✓ | ✓ | ✓ | ||
Nested tables + vMerge / gridSpan | ✓ | ✓ | ✓ | ✓ | |
Repeating tblHeader / cantSplit / textDirection | ✓ | ✓ | ✓ | ||
SDT content controls (w:sdt) | ✓ | ✓ | ✓ | ||
Template ${var | pipe} + ${block} / ${if} | ✓ | ✓ | templates | ||
| O(1) stream extract | ✓ | ||||
Merge with style / bookmark / rId isolation | ✓ | ✓ | |||
Tiled / image watermark + w:permStart exceptions | ✓ | ✓ | ✓ |
PHPWord is the API ancestor. unioffice is a paid, multi-format Office SDK. The two lightweight Go writers cover paragraphs (and, for go-docx, pictures and tables) and stop short of OMML, charts, streaming extract, and identifier-safe merge.
package main
import (
"log"
"github.com/yunkeweb/go-word"
)
func main() {
doc := word.New()
doc.SetDefaultFontName("Calibri")
sec := doc.AddSection()
sec.AddTitle("GoWord v0.11.0", 1)
sec.AddSDTText("Full name", "full_name", "Enter full name")
sec.AddMath(`\frac{a}{b}`)
doc.SetTextWatermark("CONFIDENTIAL", word.WatermarkOptions{Tile: true, Angle: -45})
if err := doc.Save("hello.docx"); err != nil {
log.Fatal(err)
}
}go get github.com/yunkeweb/go-word@v0.11.0Continue with Installation, Quick Start, SDT, Tables, Watermark & Protection, and the four Enterprise Recipes. Full signatures live on pkg.go.dev.