2026 年 Go PDF ライブラリ徹底比較
2026 年時点で稼働する Go の PDF ライブラリを 4 種のワークロードでベンチ。ライセンス・依存・保守状況を横並びで比較する。
TL;DR
5 年前、「Go で PDF」で検索するとほぼ確実に jung-kurt/gofpdf にたどり着いた。今、それはアーカイブされている。コミュニティフォークの go-pdf/fpdf も同じ。実質的に選択肢は、検索結果が示唆するよりずっと少ない。
- 現役でメンテされている: gpdf (このチーム), signintech/gopdf, johnfercher/maroto v2 — ただし Maroto はアーカイブ済みの gofpdf に依存している。
- アーカイブ: jung-kurt/gofpdf (2021), go-pdf/fpdf (2025)。
- 商用 / AGPL: unidoc/unipdf。
この記事では現役ライブラリを 4 つのワークロードでベンチし、ライセンスと依存グラフと保守状況を横並びで並べる。用途別の選び方も最後に置く。来年も同じ構成で更新する予定。
バイアスの開示: 私たちは gpdf のチーム。ベンチマークコードは公開 (_benchmark/benchmark_test.go) している。手元でクローンして再計測してほしい。数字が違えば教えてほしい。
「Go PDF ライブラリ」は 3 種類ある
ひとくちに「Go PDF ライブラリ」と言っても、実は違う 3 種類が同じ棚に並んでいる:
- 低レベル PDF ライター — バイトを書いてプリミティブで描画する。
jung-kurt/gofpdf,signintech/gopdf。 - ライターをラップするレイアウトライブラリ — 宣言的に行と列を組む。
johnfercher/maroto v2,gpdf。 - フルドキュメントスイート — 解析・署名・PDF/A・OCR・赤塗りまで含む。
unidoc/unipdf。
「一番良い Go PDF ライブラリはどれ?」の質問が Qiita や Reddit で噛み合わないのは、この 3 つが混ざったまま議論するから。以下の比較では毎節でこの区別を意識する。
ラインナップから外したもの: ヘッドレス Chromium を立ち上げる系 (go-rod, chromedp)。あれは PDF ライブラリではなく「印刷する機能を持ったブラウザ」。デザイナーから上がってくる HTML/CSS をピクセル精度で再現したいならあれが正解だが、コールドスタートもメモリも distroless 運用も全部重い。この記事の比較対象には含めない。
スコアボード
| ライブラリ | 最終リリース | アーカイブ | ライセンス | コア依存 | CJK | レイアウトグリッド | 2026 年時点 |
|---|---|---|---|---|---|---|---|
| gpdf (このチーム) | 稼働中 | — | MIT | 0 | ネイティブ | 12 カラム | メンテ中 |
| signintech/gopdf | 稼働中 | — | MIT | 0 | TTF 手動 | なし | メンテ中 |
| johnfercher/maroto v2 | 稼働中 | — | MIT | gofpdf (アーカイブ) | gofpdf 経由 | 行/列 | 土台が死んだ状態 |
| jung-kurt/gofpdf | 2021 | 2021-09-08 | MIT | 0 | AddUTF8Font | なし | アーカイブ |
| go-pdf/fpdf | 2023 | 2025 | MIT | 0 | AddUTF8Font | なし | アーカイブ |
| unidoc/unipdf | 稼働中 | — | AGPL-3.0 / 商用ライセンス | 多数 | あり | なし | 商用 |
押さえるべき点が 3 つ。半数がアーカイブ済み。Maroto は自身は現役だが土台が死んでいる — ビルドは通っても供給網の問題がある。そして AGPL を受け入れられない組織にとって unidoc の選定は技術の問題ではなく ライセンス調達の問題 になる。
ベンチマーク
コード: gpdf リポジトリの _benchmark/benchmark_test.go。環境は Apple M1 (Max, 32 GB, macOS 14.5)、Go 1.25、CGO なし。各ケースは最低 5 秒の実時間回している。-benchmem を有効化し、ns/op とアロケーション数を計測。
4 つのケースを選んだのは、現場で実際に生成されるものの形に近いから:
- ページ 1 枚の hello world — 1 ページ、1 行テキスト、1 フォント。生成時固定オーバーヘッドの床。
- 4 列 10 行の請求書テーブル — ヘッダ行 + ボディ 10 行 + カラム整列 + 細枠。「請求書を作る」ときの形。
- 100 ページのページ付きレポート — ヘッダ・フッタ・ページ番号・本文の反復。ページ分割コストを測る。
- 複雑な CJK 請求書 — 平仮名・片仮名・漢字混在、4 列 15 行の明細表、ヘッダ・フッタ・ページ番号、NotoSansJP の TrueType サブセット埋め込み。
含めなかったもの: unidoc/unipdf。バイナリがライセンスゲートされており、彼らの公開ベンチの方法論を一般公開リポジトリに移植すると誤解を招く。unidoc を検討中なら、公式が自社ベンチを公開しているのでそちらを参照してほしい。
結果
| ワークロード | gpdf | signintech/gopdf | Maroto v2 | gofpdf | go-pdf/fpdf |
|---|---|---|---|---|---|
| 1 ページ hello world | 13 µs | 423 µs | 237 µs | 132 µs | 135 µs |
| 4×10 請求書テーブル | 108 µs | 835 µs | 8,600 µs | 241 µs | 243 µs |
| 100 ページのレポート | 683 µs | 8,600 µs | 19,800 µs | 11,700 µs | 11,900 µs |
| 複雑な CJK 請求書 | 133 µs | 997 µs | 10,400 µs | 254 µs | n/a |
go-pdf/fpdf の CJK 欄が n/a なのは、検証したバージョンで AddUTF8Font 経路が NotoSansJP の cmap format 12 テーブル読み取り時にパニックするため。パッチで直せるが、フォーク自身がアーカイブされておりリリースは来ない。
数字の読み方
順位はワークロードを跨いでも安定している。すべてのケースで gpdf は 2 番手の 10〜30 倍速い。これは奇抜なトリックではなく、3 つの設計が積み重なった結果:
1 パスのレイアウト。gpdf は中間 AST を構築してから直列化する、という段階を踏まない。ビルダーが解決した時点で直接 PDF content stream に書き出すため、他ライブラリより約半分のアロケーションで済む。100 ページベンチで 683 µs と 19,800 µs の差が出るのは、チューニングの差ではなく アーキテクチャが違う ため。
ホットパスにリフレクションを置かない。レイアウトエンジンが触る型はすべて具象型。個々は微最適化だが、100 ページレポートのプロファイルではインタフェースのディスパッチが無視できない重さで出てくる。そこを避けてある。
cmap をキャッシュする TrueType サブセッター。gofpdf はグリフ参照のたびに cmap テーブルを読み直す。gpdf は一度解決してキャッシュする。Latin だけならほぼ差が出ないが、CJK では 1 段落が漢字 + 仮名 + 約物で 150 グリフを触ることがあり、「同期生成で間に合う」と「キューに回す」の境目になる。
ベンチ表だけ見ると見落とす注意点を 1 つ: 絶対速度は思ったほど重要ではない。重要なのは「リクエストパスで同期生成しても大丈夫か」の閾値。hello world ならこの閾値はどのライブラリも越える。100 ページレポートで越えるのは gpdf だけ。最大サイズが 1 ページ領収書なら、現役 4 つはどれでも問題ない。API の使い心地とライセンスで選んで良い。
依存
それぞれを go get 直後に go mod graph した結果:
| ライブラリ | 外部モジュール | 推移的にアーカイブ依存あり |
|---|---|---|
| gpdf (コア) | 0 | — |
| signintech/gopdf | 0 | — |
| gofpdf | 0 (ただし自身がアーカイブ) | 自身 |
| go-pdf/fpdf | 0 (ただし自身がアーカイブ) | 自身 |
| johnfercher/maroto v2 | gofpdf (2021 アーカイブ) | あり — gofpdf |
| unidoc/unipdf | 多数 (画像・暗号・圧縮) | アーカイブは無し |
「本番の依存にアーカイブ済みリポジトリを入れない」という社内 lint ルールを持つチームでは、今日の Maroto v2 はこれで落ちる。Maroto のメンテナは 1 年以上かけて gofpdf 依存の排除を進めていて、それが完了したらこの行は変わる。この記事を書いた時点と読んでいる時点で状態がずれている可能性があるので、判断前に Maroto リポジトリの現状を確認したほうがいい。
ライセンス
| ライブラリ | ライセンス |
|---|---|
| gpdf (コア) | MIT |
| signintech/gopdf | MIT |
| johnfercher/maroto v2 | MIT |
| gofpdf | MIT |
| go-pdf/fpdf | MIT |
| unidoc/unipdf | AGPL-3.0 または商用ライセンス |
unidoc の AGPL はかなり強い側。ユーザがネットワーク越しに触るサーバで使うなら、サーバ側コードも AGPL で公開する必要がある — ほとんどのクローズドソース SaaS では実質不可。結果的に商用ライセンスが唯一の現実解になり、価格は公開されていない。営業とのやりとりが前提。
GitHub スター数の比較で最も見落とされるのがここ。unidoc は機能もスターも最多。だが、ほとんどの商用ユースケースで「買う」の意思決定がセットになる。unidoc を貶める意図はない — モデルは正当だし製品は優秀。ただし go get する前に把握しておくべき。
保守状況 (平易な言い方で)
- gpdf — 主メンテナはこのチーム (gpdf-dev)。リリースは 2〜4 週間ごと、ロードマップはリポジトリ内、CI は Go 1.22〜1.26 で回している。メインリポジトリの issue 対応は数営業日以内。このプロジェクトには本気。
- signintech/gopdf — 現役でコミット頻度は控えめ。issue は見てくれるし PR は数週間で取り込まれる。低レベル生成向け。
- Maroto v2 — 現役。2023 年の v2 リライトで安定。gofpdf 依存は既知で置換作業中。判断前にリポジトリを確認。
- gofpdf — 2021-09-08 アーカイブ。リポジトリには "This repository has been archived by the owner. It is now read-only." のバナー。セキュリティパッチもバグ修正も来ない。
- go-pdf/fpdf — 2025 年アーカイブ。README は別のライブラリの利用を推奨している。専用の移行ガイドを書いた: gofpdf からの移行ガイド。
- unidoc/unipdf — 現役、商用チーム、潤沢なリソース。エンタープライズサポートあり。
選び方
機能マトリクスではなく決定木で書く。「機能最多 = 正解」とは限らないから:
- 「Go コードベースで請求書・レポート・書類を生成する。MIT を好み、依存ゼロが良く、CJK が混ざることがある」 → gpdf。
- 「カスタム図形を描く低レベル生成がメインで、小さくて安定した手動寄りのライブラリが欲しい」 → signintech/gopdf。
- 「Maroto 的なレイアウトコードが既に稼働している」 → gofpdf 排除が完了するまで Maroto v2 を維持、その後再評価。API 自体は悪くない。
- 「PDF/A・OCR・赤塗り・電子署名が必要で、会社が商用ライセンスを出せる」 → unidoc/unipdf。最初にライセンスの話を詰めること。
- 「今も gofpdf で、動いている」 → 今日は大丈夫。関連依存の CVE が出て詰む前に移行計画を立てる。移行ガイドはこちら。
- 「HTML/CSS をピクセル精度で PDF 化したい」 → 上記のどれでもない。go-rod / chromedp + ヘッドレス Chromium、コールドスタートコストは覚悟の上で。
私たちは gpdf のチームなので、1 つ目と 5 つ目の多くで gpdf が妥当と思っている — 当然のバイアスがある。ベンチコードを読んで、自分で回して、この表を鵜呑みにしないでほしい。
30 行で書く gpdf 例
「一番速い」「依存グラフが最小」は、コードが読めなければ意味がない。完全に動く請求書 1 ページ、疑似コードも省略なしで:
package main
import (
"log"
"os"
"github.com/gpdf-dev/gpdf"
"github.com/gpdf-dev/gpdf/document"
"github.com/gpdf-dev/gpdf/pdf"
"github.com/gpdf-dev/gpdf/template"
)
func main() {
doc := gpdf.NewDocument(
gpdf.WithPageSize(document.A4),
gpdf.WithMargins(document.UniformEdges(document.Mm(20))),
)
page := doc.AddPage()
page.AutoRow(func(r *template.RowBuilder) {
r.Col(12, func(c *template.ColBuilder) {
c.Text("請求書 #2026-0042", template.Bold(), template.FontSize(20))
c.Spacer(document.Mm(6))
c.Table(
[]string{"品目", "数量", "単価", "金額"},
[][]string{
{"フロントエンド開発", "40 時間", "¥15,000", "¥600,000"},
{"バックエンド開発", "60 時間", "¥15,000", "¥900,000"},
{"UI デザイン", "20 時間", "¥12,000", "¥240,000"},
},
template.ColumnWidths(50, 15, 15, 20),
template.TableHeaderStyle(
template.Bold(),
template.TextColor(pdf.White),
template.BgColor(pdf.RGBHex(0x1A237E)),
),
)
})
})
data, err := doc.Generate()
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("invoice.pdf", data, 0o644); err != nil {
log.Fatal(err)
}
}
SetXY ゼロ。列幅の手計算ゼロ。gpdf.WithFont("NotoSansJP", ttfBytes) をドキュメントオプションに足せば、上記の日本語がそのままレンダリングされる。豆腐にならない。
載せなかったもの
比較記事には必ず「入れなかった理由」の節がある。ここも同じ:
- 社内フォークの gofpdf。本番運用されているクローズドフォークはある。コードが見えない以上ベンチできない。
pdfcpu。「Go PDF ライブラリ」の一覧には必ず載るが、主用途は PDF プロセッサ (マージ・分割・暗号化・スタンプ) であって生成ではない。この記事の対象外。処理系向けの記事を別で書く予定。gotenbergやヘッドレスブラウザサービスのラッパー。ライブラリではないし、公平な比較にならない。- 自家製
gpdfのベンチ。比較の焦点はコアの数字。
FAQ
なぜ gpdf は gofpdf の 10 倍速いのか? 何か魔法か? 魔法はない。3 つの設計が積み上がっている: 1 パスレイアウト (ビルダーとライター間に AST を置かない)、ホットパスの具象型、cmap をキャッシュする TrueType サブセッター。どれか 1 つでも 2 倍の改善。重ねて桁が変わる。
このベンチ、手元で本当に再現できる?
できる。git clone https://github.com/gpdf-dev/gpdf && cd gpdf/_benchmark && go test -bench=. -benchmem。同じ CPU アーキ・同じ Go バージョンで数字が合わなければ issue を立ててほしい。ベンチ結果のドリフトは起きるし、知りたい。
gofpdf は復活する? 現実的にはしない。最後のコミットは 2021 年。issue tracker はクローズ済み。仮に誰かが開け直したとしても、カーソル + シングルバイトフォント + グリッドなしというアーキテクチャは 2026 年のスタート地点としては正しくない。歴史的遺物として扱って、移行するのが実利的。
Java iText / Python ReportLab / Node pdfkit はどう? 言語横断ベンチは別記事のネタ。短く書くと: Go はスループットとコールドスタートでは勝つが、機能の幅 (特に HTML→PDF の忠実度) では負ける。既に Go のチームなら gpdf のほうが軽くて速い。Python や Node のチームが Go に移ろうとすると移行コストがかかるので、大量トラフィックでのみ投資対効果が出る。
競合が改善したらこの比較は公平性を保てる? 保つ。毎年回す。signintech/gopdf がテーブル API を出して所要時間が半分になれば、2027 年版にそう書く。Maroto v2 が gofpdf 排除を完了すれば、その行は書き換わる。誰かに信じてもらう必要がないよう、ベンチコードは意図的に公開している。
gpdf を使ってみる
gpdf は Go の PDF ライブラリ。MIT、ゼロ依存、ネイティブ CJK 対応。
go get github.com/gpdf-dev/gpdf
次に読む
- gofpdf はアーカイブされた。gpdf への移行ガイド — 5 組の Before/After コードで API マッピング全体を説明。
- Quickstart —
go.modまで含めて 5 分で動く。 - ベンチマークコードそのもの:
_benchmark/benchmark_test.go。