gofpdf是Go生态导出PDF最可靠的选择,纯Go实现、无CGO依赖、交叉编译友好;需注意AddPage()必须先调用、中文须显式注册TTF字体、大文件应禁用压缩并流式写入。

gofpdf 是目前 Go 生态中导出 PDF 文件最可靠的选择——纯 Go 实现、无 CGO、不依赖系统库,交叉编译后单文件可直接运行。它不适合渲染 HTML 或做自动分页长文,但导出发票、报表、合同摘要这类结构化文档,又快又稳。
导出失败却没报错?先检查 OutputFileAndClose 路径和权限
常见现象是调用 pdf.OutputFileAndClose("out.pdf") 后文件没生成,也不 panic,只返回 nil 错误。
- 当前工作目录不可写(尤其容器或 systemd 服务里,默认
/或/tmp可能受限) - 路径含非法字符:Windows 下用
"./out.pdf"没问题,但若拼成"C:\temp\out.pdf"且没转义反斜杠,会静默失败 - 父目录不存在:
os.MkdirAll(filepath.Dir("dist/report.pdf"), 0755)必须在OutputFileAndClose前执行 - 更稳妥的替代:用
pdf.WriteTo("dist/report.pdf", 0644),它显式接受权限参数,出错时 error 更明确
AddPage() 必须在写任何内容前调用,否则输出为空白或 panic
gofpdf.New() 只初始化对象,不创建页面;所有文字、表格、图片都必须落在某一页上。
- 漏掉
pdf.AddPage(),后续Cell()、MultiCell()都不会生效,最终 PDF 是空白页或触发 index out of range - 多页文档中,每页开头都要调一次
AddPage(),不能只在初始化后调一次 - 如果用了页眉/页脚钩子(
SetHeaderFunc),AddPage()后需重新注册,它不会自动继承
中文显示方块?不是编码问题,是字体链断了
方块 ≠ UTF-8 编码错误,而是 gofpdf 找不到对应字形。默认 CoreFont(如 Helvetica)根本不含中文。
- 必须下载支持简体中文的 TTF 文件(推荐
NotoSansCJKsc-Regular.ttf,开源无版权风险) - 注册时路径必须可读:
pdf.AddFont("noto", "", "./fonts/NotoSansCJKsc-Regular.ttf")—— 注意用正斜杠,Windows 下反斜杠会静默忽略 - 注册后**立刻**切换:
pdf.SetFont("noto", "", 12);名字必须和AddFont第一个参数完全一致 - 别用 Windows 自带的
simhei.ttf:部分版本含保护头,gofpdf 加载失败且不报错
导出大文件内存暴涨或卡死?关压缩 + 流式写入
生成 30+ 页报表时,pdf.Output() 默认启用压缩,会把整个 PDF 内存缓存再编码,容易 OOM。
立即学习“go语言免费学习笔记(深入)”;
- 初始化时禁用压缩:
pdf := gofpdf.New("P", "pt", "A4", ""); pdf.Compress = false - 避免一次性调
Output()得到[]byte再写磁盘;改用WriteTo()直接流式落盘 - 生成超 50 页文档时,在循环中适当调
runtime.GC(),防止 goroutine 积压未释放内存 - 别在循环里反复
AddFont()—— 字体注册一次即可,重复会 panic 报font already exists
MultiCell() 后务必用 pdf.GetY() 检查当前位置,而不是靠经验硬写 SetY(200)。



















