gofpdf是go生成pdf的入门首选,因其纯go实现、api简洁、无外部依赖,适合报表等结构化文档;但需注意单位设置、中文字体注册与路径、multicell换行不分页等问题。

Go 生成 PDF 不靠模板引擎就硬写,基本等于自建排版引擎——别这么干。用 gofpdf 或 unidoc 是合理选择,但要注意许可证和中文支持这俩坑。
为什么 gofpdf 是入门首选(而非 pdfcpu 或原生 bytes.Buffer)
gofpdf 封装了底层 PDF 结构,提供类 HTML 的流式 API,比如 AddPage()、SetFontSize()、Cell(),适合快速导出报表、票据这类结构化文档。而 pdfcpu 更偏向 PDF 元数据操作与合并,不擅长从零绘图;手撸 PDF 格式则要处理对象流、xref 表、交叉引用,连 CRLF 换行都可能让 Adobe Reader 报错。
- 中文显示必须显式注册字体:调用
AddFont()加载simhei.ttf或NotoSansCJKsc-Regular.ttf,否则输出全是方块 -
gofpdf默认不启用 UTF-8,需在NewPDF()后立刻调用SetDisplayMode("real", "continuous")并设置SetTextColor(0, 0, 0)避免乱码叠加 - 它不支持 CSS,表格只能靠多次
Cell()手动对齐,列宽需预估字符数 × 字号 × 0.5(中文字体下经验系数)
导出含图表的 PDF 时,unidoc 和 gofpdf 怎么选
如果 PDF 里要嵌入 plot 生成的 PNG 或 SVG 转位图,gofpdf 只能加载 PNG/JPEG;unidoc 支持嵌入矢量图形但要付费授权(社区版限制页数且带水印)。实际项目中,90% 场景用 gofpdf.Image() + os.Create("report.pdf") 写入即可。
- 图片路径必须是绝对路径或基于可执行文件所在目录的相对路径,
./assets/chart.png在 Docker 容器里常因工作目录不同失效 -
ImageOptions{ImageType: "PNG", ReadDpi: true}能读取 PNG DPI 元信息,避免缩放失真;不设这个,gofpdf默认按 72 DPI 渲染,图表会糊 - 若图表来自 HTTP 接口,先用
http.Get()下载到bytes.Buffer,再传给ImageFromBytes(),别直接传 URL 字符串——gofpdf不支持远程图
io.Writer 导出 PDF 到 HTTP 响应时的 Content-Type 和缓存陷阱
直接 w.Header().Set("Content-Type", "application/pdf") 不够,浏览器可能仍弹保存对话框或打开空白页。关键是 Content-Disposition 头和响应体写入顺序。
- 必须在调用
pdf.Output(w)前设置全部 header,一旦开始写 body,header 就锁死 - 下载文件名含中文要用
filename*=UTF-8''%E6%8A%A5%E8%A1%A8.pdf编码,不能只写filename="报表.pdf",否则 Chrome 显示乱码 - 加
w.Header().Set("Cache-Control", "no-store"),否则 Nginx 或 CDN 可能缓存旧 PDF,用户反复下载到上一版
真正麻烦的不是生成 PDF,而是让中文字体在各种环境(macOS 开发机、Alpine Linux 容器、Windows CI)下都能被 gofpdf 正确加载——路径、编码、字体子集、甚至 ttf 文件末尾多一个空格都会导致 font not found 错误却不报 panic。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











