[{"data":1,"prerenderedAt":1846},["ShallowReactive",2],{"blog-zh-go-pdf-library-showdown-2026":3},{"id":4,"title":5,"author":6,"body":9,"date":1833,"description":1834,"draft":1835,"extension":1836,"howTo":1837,"image":1837,"meta":1838,"navigation":810,"path":1839,"seo":1840,"stem":1841,"tags":1842,"updated":1837,"__hash__":1845},"blogZh/zh/blog/002.go-pdf-library-showdown-2026.md","2026 年 Go PDF 库终极对决",{"name":7,"url":8},"gpdf team","https://gpdf.dev",{"type":10,"value":11,"toc":1815},"minimark",[12,17,26,48,51,59,63,66,103,106,109,112,304,310,313,329,332,358,364,368,476,485,488,495,504,510,516,523,526,537,614,617,619,673,676,682,685,726,729,732,773,776,780,783,1650,1661,1664,1667,1706,1710,1716,1726,1732,1738,1744,1748,1751,1768,1781,1784,1811],[13,14,16],"h2",{"id":15},"tldr","TL;DR",[18,19,20,21,25],"p",{},"5 年前，搜索\"Go PDF\"几乎必然落在 ",[22,23,24],"strong",{},"jung-kurt/gofpdf","。今天，它已归档。社区 fork go-pdf/fpdf 也归档了。真正的选择比搜索结果暗示的少得多：",[27,28,29,36,42],"ul",{},[30,31,32,35],"li",{},[22,33,34],{},"仍在积极维护","：gpdf（本团队）、signintech/gopdf、johnfercher/maroto v2 —— 但 Maroto 仍依赖已归档的 gofpdf。",[30,37,38,41],{},[22,39,40],{},"已归档","：jung-kurt/gofpdf（2021）、go-pdf/fpdf（2025）。",[30,43,44,47],{},[22,45,46],{},"商用 / AGPL","：unidoc/unipdf。",[18,49,50],{},"本文在 4 种工作负载上对现役库做基准测试，列出许可证与依赖图，给出按用例的推荐。明年再跑一次。",[18,52,53,54,58],{},"偏见声明：我们是 gpdf 团队。基准测试代码公开（",[55,56,57],"code",{},"_benchmark/benchmark_test.go","），欢迎自行克隆复测，若数字对不上请告知。",[13,60,62],{"id":61},"go-pdf-库其实是三种东西","\"Go PDF 库\"其实是三种东西",[18,64,65],{},"\"Go PDF 库\"这个短语至少盖住 3 种不同的东西：",[67,68,69,82,94],"ol",{},[30,70,71,74,75,77,78,81],{},[22,72,73],{},"低层 PDF 写入器"," —— 推字节、用图元绘制。",[55,76,24],{},"、",[55,79,80],{},"signintech/gopdf","。",[30,83,84,87,88,77,91,81],{},[22,85,86],{},"包装写入器的布局库"," —— 声明式的行列。",[55,89,90],{},"johnfercher/maroto v2",[55,92,93],{},"gpdf",[30,95,96,99,100,81],{},[22,97,98],{},"完整文档套件"," —— 解析、签名、PDF/A、OCR、涂黑。",[55,101,102],{},"unidoc/unipdf",[18,104,105],{},"不明确类别就问\"哪个 Go PDF 库最好\"，是 Reddit / 知乎上的讨论跑偏的主因。下文每节都尽量保持这个区分清晰。",[18,107,108],{},"未列入：任何调起 headless Chromium 的方案（go-rod、chromedp）。它们不是 PDF 库，是\"会打印的浏览器\"。对 CSS 重的设计还原度好，但冷启动慢、内存大、不适合 distroless。如果需求是\"设计师给我 HTML/CSS，要像素级精确\"，那些工具存在，本文不参与那块比较。",[13,110,111],{"id":111},"记分板",[113,114,115,146],"table",{},[116,117,118],"thead",{},[119,120,121,125,128,131,134,137,140,143],"tr",{},[122,123,124],"th",{},"库",[122,126,127],{},"最后发布",[122,129,130],{},"归档",[122,132,133],{},"许可证",[122,135,136],{},"核心依赖",[122,138,139],{},"CJK",[122,141,142],{},"布局栅格",[122,144,145],{},"2026 状态",[147,148,149,182,202,226,253,280],"tbody",{},[119,150,151,157,160,163,166,171,174,177],{},[152,153,154,156],"td",{},[22,155,93],{},"（本团队）",[152,158,159],{},"活跃",[152,161,162],{},"—",[152,164,165],{},"MIT",[152,167,168],{},[22,169,170],{},"0",[152,172,173],{},"原生",[152,175,176],{},"12 栅格",[152,178,179],{},[22,180,181],{},"维护中",[119,183,184,186,188,190,192,194,197,200],{},[152,185,80],{},[152,187,159],{},[152,189,162],{},[152,191,165],{},[152,193,170],{},[152,195,196],{},"手动 TTF",[152,198,199],{},"无",[152,201,181],{},[119,203,204,206,208,210,212,217,220,223],{},[152,205,90],{},[152,207,159],{},[152,209,162],{},[152,211,165],{},[152,213,214],{},[22,215,216],{},"gofpdf（已归档）",[152,218,219],{},"经 gofpdf",[152,221,222],{},"行/列",[152,224,225],{},"地基已死",[119,227,228,230,233,238,240,242,247,249],{},[152,229,24],{},[152,231,232],{},"2021",[152,234,235],{},[22,236,237],{},"2021-09-08",[152,239,165],{},[152,241,170],{},[152,243,244],{},[55,245,246],{},"AddUTF8Font",[152,248,199],{},[152,250,251],{},[22,252,40],{},[119,254,255,258,261,266,268,270,274,276],{},[152,256,257],{},"go-pdf/fpdf",[152,259,260],{},"2023",[152,262,263],{},[22,264,265],{},"2025",[152,267,165],{},[152,269,170],{},[152,271,272],{},[55,273,246],{},[152,275,199],{},[152,277,278],{},[22,279,40],{},[119,281,282,284,286,288,293,296,299,301],{},[152,283,102],{},[152,285,159],{},[152,287,162],{},[152,289,290],{},[22,291,292],{},"AGPL-3.0 / 商用",[152,294,295],{},"多",[152,297,298],{},"有",[152,300,199],{},[152,302,303],{},"商用",[18,305,306,307,81],{},"要注意 3 点。半数已归档。Maroto 自身在维护，但地基没人管 —— 即便今天能编译，仍是供应链问题。不接受 AGPL 的团队，unidoc 的选择不是技术问题而是 ",[22,308,309],{},"商业许可采购问题",[13,311,312],{"id":312},"基准测试",[18,314,315,316,324,325,328],{},"代码：gpdf 仓库里的 ",[317,318,322],"a",{"href":319,"rel":320},"https://github.com/gpdf-dev/gpdf/tree/main/_benchmark",[321],"nofollow",[55,323,57],{},"。环境：Apple M1（Max, 32 GB, macOS 14.5），Go 1.25，无 CGO。每个用例至少跑 5 秒实时，",[55,326,327],{},"-benchmem"," 打开，记录 ns/op 和分配次数。",[18,330,331],{},"挑这 4 个场景是因为它们接近生产中实际生成的东西，不是合成玩具：",[67,333,334,340,346,352],{},[30,335,336,339],{},[22,337,338],{},"单页 hello world","。1 页、1 行字、1 字体。每文档固定开销的下限。",[30,341,342,345],{},[22,343,344],{},"4 列 10 行发票表","。表头 + 10 行内容 + 列对齐 + 细边框。\"生成发票\"的形状。",[30,347,348,351],{},[22,349,350],{},"100 页分页报表","。重复页眉、页脚、页码，每页正文。度量分页成本。",[30,353,354,357],{},[22,355,356],{},"复杂 CJK 发票","。日文（平假名、片假名、汉字）混排，4 列 15 行明细、页眉、带页码的页脚，嵌入 NotoSansJP TrueType 子集。",[18,359,360,361,363],{},"未纳入：",[55,362,102],{},"。其二进制由许可证门控，在公开基准仓库里复现其发布方法论会产生误导。若在评估 unidoc，请跑其官方基准。",[365,366,367],"h3",{"id":367},"结果",[113,369,370,389],{},[116,371,372],{},[119,373,374,377,379,381,384,387],{},[122,375,376],{},"工作负载",[122,378,93],{},[122,380,80],{},[122,382,383],{},"Maroto v2",[122,385,386],{},"gofpdf",[122,388,257],{},[147,390,391,412,434,455],{},[119,392,393,395,400,403,406,409],{},[152,394,338],{},[152,396,397],{},[22,398,399],{},"13 µs",[152,401,402],{},"423 µs",[152,404,405],{},"237 µs",[152,407,408],{},"132 µs",[152,410,411],{},"135 µs",[119,413,414,417,422,425,428,431],{},[152,415,416],{},"4×10 发票表",[152,418,419],{},[22,420,421],{},"108 µs",[152,423,424],{},"835 µs",[152,426,427],{},"8,600 µs",[152,429,430],{},"241 µs",[152,432,433],{},"243 µs",[119,435,436,439,444,446,449,452],{},[152,437,438],{},"100 页报表",[152,440,441],{},[22,442,443],{},"683 µs",[152,445,427],{},[152,447,448],{},"19,800 µs",[152,450,451],{},"11,700 µs",[152,453,454],{},"11,900 µs",[119,456,457,459,464,467,470,473],{},[152,458,356],{},[152,460,461],{},[22,462,463],{},"133 µs",[152,465,466],{},"997 µs",[152,468,469],{},"10,400 µs",[152,471,472],{},"254 µs",[152,474,475],{},"n/a",[18,477,478,479,481,482,484],{},"go-pdf/fpdf 的 CJK 栏 ",[55,480,475],{},"：测试版本中 ",[55,483,246],{}," 在读取 NotoSansJP 的 cmap format 12 表时 panic。可修但 fork 已归档，没人发补丁。",[365,486,487],{"id":487},"读数字",[18,489,490,491,494],{},"跨场景排名稳定。在所有用例里 gpdf 比第二名 ",[22,492,493],{},"快 10–30 倍","，既不魔也不意外。3 个设计叠加：",[18,496,497,500,501,81],{},[22,498,499],{},"单遍布局","。gpdf 不构建中间 AST 再序列化。构建器在解析时直接写 PDF 内容流，分配数约为其他库的一半。100 页基准里 683 µs 对 19,800 µs 的差距，不是调参差异，是 ",[22,502,503],{},"架构不同",[18,505,506,509],{},[22,507,508],{},"热路径无反射","。布局引擎触碰的类型都是具体类型。单独看是微优化，但跨 100 页报表累积后，接口分派会在 profile 中显形。我们避开了。",[18,511,512,515],{},[22,513,514],{},"TrueType 子集器不重读 cmap","。gofpdf 每次字形查询都重读 cmap 表；gpdf 解析一次后缓存。纯 Latin 几乎无感；CJK 一段可能跨汉字、假名、标点用到 150 个字形，差距就是\"同步生成够用\"和\"要排队\"。",[18,517,518,519,522],{},"基准表看不到的告诫：",[22,520,521],{},"对大部分 PDF 工作负载，绝对速度不如人想得那么重要","。有意义的阈值是\"能不能在请求路径上同步生成\"。单页 hello world，本文所有库都过阈值；100 页报表，只有 gpdf 过。若最大文档就是一张收据，现役 4 库都行，按 API 与许可证选。",[13,524,525],{"id":525},"依赖",[18,527,528,529,532,533,536],{},"各库 ",[55,530,531],{},"go get"," 后 ",[55,534,535],{},"go mod graph"," 的结果：",[113,538,539,551],{},[116,540,541],{},[119,542,543,545,548],{},[122,544,124],{},[122,546,547],{},"外部模块",[122,549,550],{},"传递性归档依赖",[147,552,553,566,574,584,592,604],{},[119,554,555,560,564],{},[152,556,557,559],{},[22,558,93],{},"（核心）",[152,561,562],{},[22,563,170],{},[152,565,162],{},[119,567,568,570,572],{},[152,569,80],{},[152,571,170],{},[152,573,162],{},[119,575,576,578,581],{},[152,577,386],{},[152,579,580],{},"0（自身归档）",[152,582,583],{},"自身",[119,585,586,588,590],{},[152,587,257],{},[152,589,580],{},[152,591,583],{},[119,593,594,596,601],{},[152,595,90],{},[152,597,598],{},[22,599,600],{},"gofpdf（2021 归档）",[152,602,603],{},"是 — gofpdf",[119,605,606,608,611],{},[152,607,102],{},[152,609,610],{},"多（图像、加密、压缩）",[152,612,613],{},"无归档",[18,615,616],{},"有\"生产依赖禁止归档仓库\"lint 规则的团队，今天的 Maroto v2 会被这条挡下。Maroto 维护者一年多来在替换 gofpdf，完成后此行会变。请在决策前确认 Maroto 仓库的当前状态。",[13,618,133],{"id":133},[113,620,621,629],{},[116,622,623],{},[119,624,625,627],{},[122,626,124],{},[122,628,133],{},[147,630,631,638,644,650,656,662],{},[119,632,633,636],{},[152,634,635],{},"gpdf（核心）",[152,637,165],{},[119,639,640,642],{},[152,641,80],{},[152,643,165],{},[119,645,646,648],{},[152,647,90],{},[152,649,165],{},[119,651,652,654],{},[152,653,386],{},[152,655,165],{},[119,657,658,660],{},[152,659,257],{},[152,661,165],{},[119,663,664,668],{},[152,665,666],{},[22,667,102],{},[152,669,670],{},[22,671,672],{},"AGPL-3.0 或商用许可",[18,674,675],{},"unidoc 的 AGPL 条款严格：若用于用户通过网络交互的服务器，你的服务器端代码也必须以 AGPL 发布 —— 多数闭源 SaaS 无法接受。实际上商用许可成为唯一可行路径，价格不公开，需与销售沟通。",[18,677,678,679,681],{},"GitHub star 比较中最常被忽视的就是此处。unidoc 功能最多、星最多，但许可证对多数商用用例关上门（需购买）。并非贬低 unidoc —— 商业模式合理、产品优秀 —— 只是 ",[55,680,531],{}," 前请心里有数。",[13,683,684],{"id":684},"维护状况",[27,686,687,692,697,702,712,721],{},[30,688,689,691],{},[22,690,93],{}," —— 主维护者为本团队（gpdf-dev）。每 2–4 周发布一次；路线图在 repo 内；CI 覆盖 Go 1.22–1.26；主 repo 的 issue 数工作日内回应。",[30,693,694,696],{},[22,695,80],{}," —— 活跃，提交节奏较慢。issue 会被看，PR 一般数周内合并。主用途仍是低层生成。",[30,698,699,701],{},[22,700,383],{}," —— 活跃。v2 在 2023 年落地后稳定。gofpdf 依赖已知、正在替换。决策前看 repo 当前状态。",[30,703,704,706,707,711],{},[22,705,386],{}," —— 2021-09-08 归档。仓库横幅：",[708,709,710],"em",{},"\"This repository has been archived by the owner. It is now read-only.\""," 不发安全补丁、不修 bug。",[30,713,714,716,717,81],{},[22,715,257],{}," —— 2025 年归档。README 建议改用其他库。我们写了专门的迁移指南：",[317,718,720],{"href":719},"/zh/blog/gofpdf-migration","gofpdf 已归档：迁移到 gpdf",[30,722,723,725],{},[22,724,102],{}," —— 活跃，商业团队，资源充足，提供企业支持。",[13,727,728],{"id":728},"怎么选",[18,730,731],{},"给决策树而不是功能矩阵。\"功能最多\"往往不是正确问题：",[27,733,734,740,746,752,758,767],{},[30,735,736,739],{},[22,737,738],{},"\"Go 代码库要生成发票、报表、文档，希望 MIT、零依赖，文档中偶尔有 CJK。\""," → gpdf。",[30,741,742,745],{},[22,743,744],{},"\"低层 PDF 生成，带自定义几何，想要小、稳、手动控制的库。\""," → signintech/gopdf。",[30,747,748,751],{},[22,749,750],{},"\"已有 Maroto 风格的布局代码，能跑。\""," → 保持 Maroto v2 直到 gofpdf 替换落地后再评估。API 本身不是问题。",[30,753,754,757],{},[22,755,756],{},"\"需要 PDF/A、OCR、涂黑、电子签名，公司愿意付商用许可费。\""," → unidoc/unipdf，先谈许可证。",[30,759,760,763,764,81],{},[22,761,762],{},"\"仍在 gofpdf 上，跑得好好的。\""," → 今天没事。在下一个相关依赖 CVE 出现前规划迁移。",[317,765,766],{"href":719},"迁移指南",[30,768,769,772],{},[22,770,771],{},"\"需要像素级 HTML/CSS 转 PDF。\""," → 以上都不行。用 go-rod / chromedp + headless Chromium，接受冷启动成本。",[18,774,775],{},"我们是 gpdf 团队，自然认为第 1 和第 5 类的大多数场景 gpdf 是合理默认 —— 偏见在所难免。请读基准代码、在本地跑一跑，别照单全收这张表。",[13,777,779],{"id":778},"_30-行的-gpdf-示例","30 行的 gpdf 示例",[18,781,782],{},"\"最快\"与\"依赖图最小\"只有代码能读时才有意义。完整可运行的发票一页，无伪代码、无省略 import：",[784,785,790],"pre",{"className":786,"code":787,"language":788,"meta":789,"style":789},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","package main\n\nimport (\n    \"log\"\n    \"os\"\n\n    \"github.com/gpdf-dev/gpdf\"\n    \"github.com/gpdf-dev/gpdf/document\"\n    \"github.com/gpdf-dev/gpdf/pdf\"\n    \"github.com/gpdf-dev/gpdf/template\"\n)\n\nfunc main() {\n    doc := gpdf.NewDocument(\n        gpdf.WithPageSize(document.A4),\n        gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n    )\n\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"发票 #2026-0042\", template.Bold(), template.FontSize(20))\n            c.Spacer(document.Mm(6))\n            c.Table(\n                []string{\"项目\", \"数量\", \"单价\", \"金额\"},\n                [][]string{\n                    {\"前端开发\", \"40 小时\", \"¥1,050\", \"¥42,000\"},\n                    {\"后端开发\", \"60 小时\", \"¥1,050\", \"¥63,000\"},\n                    {\"UI 设计\", \"20 小时\", \"¥840\",   \"¥16,800\"},\n                },\n                template.ColumnWidths(50, 15, 15, 20),\n                template.TableHeaderStyle(\n                    template.Bold(),\n                    template.TextColor(pdf.White),\n                    template.BgColor(pdf.RGBHex(0x1A237E)),\n                ),\n            )\n        })\n    })\n\n    data, err := doc.Generate()\n    if err != nil {\n        log.Fatal(err)\n    }\n    if err := os.WriteFile(\"invoice.pdf\", data, 0o644); err != nil {\n        log.Fatal(err)\n    }\n}\n","go","",[55,791,792,805,812,822,834,844,849,859,869,879,889,895,900,916,938,963,1000,1006,1011,1030,1064,1102,1151,1176,1188,1239,1250,1292,1332,1374,1380,1412,1424,1437,1459,1486,1492,1498,1504,1510,1515,1537,1553,1571,1577,1624,1639,1644],{"__ignoreMap":789},[793,794,797,801],"span",{"class":795,"line":796},"line",1,[793,798,800],{"class":799},"sMK4o","package",[793,802,804],{"class":803},"sBMFI"," main\n",[793,806,808],{"class":795,"line":807},2,[793,809,811],{"emptyLinePlaceholder":810},true,"\n",[793,813,815,819],{"class":795,"line":814},3,[793,816,818],{"class":817},"s7zQu","import",[793,820,821],{"class":799}," (\n",[793,823,825,828,831],{"class":795,"line":824},4,[793,826,827],{"class":799},"    \"",[793,829,830],{"class":803},"log",[793,832,833],{"class":799},"\"\n",[793,835,837,839,842],{"class":795,"line":836},5,[793,838,827],{"class":799},[793,840,841],{"class":803},"os",[793,843,833],{"class":799},[793,845,847],{"class":795,"line":846},6,[793,848,811],{"emptyLinePlaceholder":810},[793,850,852,854,857],{"class":795,"line":851},7,[793,853,827],{"class":799},[793,855,856],{"class":803},"github.com/gpdf-dev/gpdf",[793,858,833],{"class":799},[793,860,862,864,867],{"class":795,"line":861},8,[793,863,827],{"class":799},[793,865,866],{"class":803},"github.com/gpdf-dev/gpdf/document",[793,868,833],{"class":799},[793,870,872,874,877],{"class":795,"line":871},9,[793,873,827],{"class":799},[793,875,876],{"class":803},"github.com/gpdf-dev/gpdf/pdf",[793,878,833],{"class":799},[793,880,882,884,887],{"class":795,"line":881},10,[793,883,827],{"class":799},[793,885,886],{"class":803},"github.com/gpdf-dev/gpdf/template",[793,888,833],{"class":799},[793,890,892],{"class":795,"line":891},11,[793,893,894],{"class":799},")\n",[793,896,898],{"class":795,"line":897},12,[793,899,811],{"emptyLinePlaceholder":810},[793,901,903,906,910,913],{"class":795,"line":902},13,[793,904,905],{"class":799},"func",[793,907,909],{"class":908},"s2Zo4"," main",[793,911,912],{"class":799},"()",[793,914,915],{"class":799}," {\n",[793,917,919,923,926,929,932,935],{"class":795,"line":918},14,[793,920,922],{"class":921},"sTEyZ","    doc ",[793,924,925],{"class":799},":=",[793,927,928],{"class":921}," gpdf",[793,930,931],{"class":799},".",[793,933,934],{"class":908},"NewDocument",[793,936,937],{"class":799},"(\n",[793,939,941,944,946,949,952,955,957,960],{"class":795,"line":940},15,[793,942,943],{"class":921},"        gpdf",[793,945,931],{"class":799},[793,947,948],{"class":908},"WithPageSize",[793,950,951],{"class":799},"(",[793,953,954],{"class":921},"document",[793,956,931],{"class":799},[793,958,959],{"class":921},"A4",[793,961,962],{"class":799},"),\n",[793,964,966,968,970,973,975,977,979,982,984,986,988,991,993,997],{"class":795,"line":965},16,[793,967,943],{"class":921},[793,969,931],{"class":799},[793,971,972],{"class":908},"WithMargins",[793,974,951],{"class":799},[793,976,954],{"class":921},[793,978,931],{"class":799},[793,980,981],{"class":908},"UniformEdges",[793,983,951],{"class":799},[793,985,954],{"class":921},[793,987,931],{"class":799},[793,989,990],{"class":908},"Mm",[793,992,951],{"class":799},[793,994,996],{"class":995},"sbssI","20",[793,998,999],{"class":799},"))),\n",[793,1001,1003],{"class":795,"line":1002},17,[793,1004,1005],{"class":799},"    )\n",[793,1007,1009],{"class":795,"line":1008},18,[793,1010,811],{"emptyLinePlaceholder":810},[793,1012,1014,1017,1019,1022,1024,1027],{"class":795,"line":1013},19,[793,1015,1016],{"class":921},"    page ",[793,1018,925],{"class":799},[793,1020,1021],{"class":921}," doc",[793,1023,931],{"class":799},[793,1025,1026],{"class":908},"AddPage",[793,1028,1029],{"class":799},"()\n",[793,1031,1033,1036,1038,1041,1044,1048,1051,1054,1056,1059,1062],{"class":795,"line":1032},20,[793,1034,1035],{"class":921},"    page",[793,1037,931],{"class":799},[793,1039,1040],{"class":908},"AutoRow",[793,1042,1043],{"class":799},"(func(",[793,1045,1047],{"class":1046},"sHdIc","r",[793,1049,1050],{"class":799}," *",[793,1052,1053],{"class":803},"template",[793,1055,931],{"class":799},[793,1057,1058],{"class":803},"RowBuilder",[793,1060,1061],{"class":799},")",[793,1063,915],{"class":799},[793,1065,1067,1070,1072,1075,1077,1080,1083,1086,1089,1091,1093,1095,1098,1100],{"class":795,"line":1066},21,[793,1068,1069],{"class":921},"        r",[793,1071,931],{"class":799},[793,1073,1074],{"class":908},"Col",[793,1076,951],{"class":799},[793,1078,1079],{"class":995},"12",[793,1081,1082],{"class":799},",",[793,1084,1085],{"class":799}," func(",[793,1087,1088],{"class":1046},"c",[793,1090,1050],{"class":799},[793,1092,1053],{"class":803},[793,1094,931],{"class":799},[793,1096,1097],{"class":803},"ColBuilder",[793,1099,1061],{"class":799},[793,1101,915],{"class":799},[793,1103,1105,1108,1110,1113,1115,1118,1122,1124,1126,1129,1131,1134,1137,1139,1141,1144,1146,1148],{"class":795,"line":1104},22,[793,1106,1107],{"class":921},"            c",[793,1109,931],{"class":799},[793,1111,1112],{"class":908},"Text",[793,1114,951],{"class":799},[793,1116,1117],{"class":799},"\"",[793,1119,1121],{"class":1120},"sfazB","发票 #2026-0042",[793,1123,1117],{"class":799},[793,1125,1082],{"class":799},[793,1127,1128],{"class":921}," template",[793,1130,931],{"class":799},[793,1132,1133],{"class":908},"Bold",[793,1135,1136],{"class":799},"(),",[793,1138,1128],{"class":921},[793,1140,931],{"class":799},[793,1142,1143],{"class":908},"FontSize",[793,1145,951],{"class":799},[793,1147,996],{"class":995},[793,1149,1150],{"class":799},"))\n",[793,1152,1154,1156,1158,1161,1163,1165,1167,1169,1171,1174],{"class":795,"line":1153},23,[793,1155,1107],{"class":921},[793,1157,931],{"class":799},[793,1159,1160],{"class":908},"Spacer",[793,1162,951],{"class":799},[793,1164,954],{"class":921},[793,1166,931],{"class":799},[793,1168,990],{"class":908},[793,1170,951],{"class":799},[793,1172,1173],{"class":995},"6",[793,1175,1150],{"class":799},[793,1177,1179,1181,1183,1186],{"class":795,"line":1178},24,[793,1180,1107],{"class":921},[793,1182,931],{"class":799},[793,1184,1185],{"class":908},"Table",[793,1187,937],{"class":799},[793,1189,1191,1194,1198,1201,1203,1206,1208,1210,1213,1216,1218,1220,1222,1225,1227,1229,1231,1234,1236],{"class":795,"line":1190},25,[793,1192,1193],{"class":799},"                []",[793,1195,1197],{"class":1196},"spNyl","string",[793,1199,1200],{"class":799},"{",[793,1202,1117],{"class":799},[793,1204,1205],{"class":1120},"项目",[793,1207,1117],{"class":799},[793,1209,1082],{"class":799},[793,1211,1212],{"class":799}," \"",[793,1214,1215],{"class":1120},"数量",[793,1217,1117],{"class":799},[793,1219,1082],{"class":799},[793,1221,1212],{"class":799},[793,1223,1224],{"class":1120},"单价",[793,1226,1117],{"class":799},[793,1228,1082],{"class":799},[793,1230,1212],{"class":799},[793,1232,1233],{"class":1120},"金额",[793,1235,1117],{"class":799},[793,1237,1238],{"class":799},"},\n",[793,1240,1242,1245,1247],{"class":795,"line":1241},26,[793,1243,1244],{"class":799},"                [][]",[793,1246,1197],{"class":1196},[793,1248,1249],{"class":799},"{\n",[793,1251,1253,1256,1258,1261,1263,1265,1267,1270,1272,1274,1276,1279,1281,1283,1285,1288,1290],{"class":795,"line":1252},27,[793,1254,1255],{"class":799},"                    {",[793,1257,1117],{"class":799},[793,1259,1260],{"class":1120},"前端开发",[793,1262,1117],{"class":799},[793,1264,1082],{"class":799},[793,1266,1212],{"class":799},[793,1268,1269],{"class":1120},"40 小时",[793,1271,1117],{"class":799},[793,1273,1082],{"class":799},[793,1275,1212],{"class":799},[793,1277,1278],{"class":1120},"¥1,050",[793,1280,1117],{"class":799},[793,1282,1082],{"class":799},[793,1284,1212],{"class":799},[793,1286,1287],{"class":1120},"¥42,000",[793,1289,1117],{"class":799},[793,1291,1238],{"class":799},[793,1293,1295,1297,1299,1302,1304,1306,1308,1311,1313,1315,1317,1319,1321,1323,1325,1328,1330],{"class":795,"line":1294},28,[793,1296,1255],{"class":799},[793,1298,1117],{"class":799},[793,1300,1301],{"class":1120},"后端开发",[793,1303,1117],{"class":799},[793,1305,1082],{"class":799},[793,1307,1212],{"class":799},[793,1309,1310],{"class":1120},"60 小时",[793,1312,1117],{"class":799},[793,1314,1082],{"class":799},[793,1316,1212],{"class":799},[793,1318,1278],{"class":1120},[793,1320,1117],{"class":799},[793,1322,1082],{"class":799},[793,1324,1212],{"class":799},[793,1326,1327],{"class":1120},"¥63,000",[793,1329,1117],{"class":799},[793,1331,1238],{"class":799},[793,1333,1335,1337,1339,1342,1344,1346,1348,1351,1353,1355,1357,1360,1362,1364,1367,1370,1372],{"class":795,"line":1334},29,[793,1336,1255],{"class":799},[793,1338,1117],{"class":799},[793,1340,1341],{"class":1120},"UI 设计",[793,1343,1117],{"class":799},[793,1345,1082],{"class":799},[793,1347,1212],{"class":799},[793,1349,1350],{"class":1120},"20 小时",[793,1352,1117],{"class":799},[793,1354,1082],{"class":799},[793,1356,1212],{"class":799},[793,1358,1359],{"class":1120},"¥840",[793,1361,1117],{"class":799},[793,1363,1082],{"class":799},[793,1365,1366],{"class":799},"   \"",[793,1368,1369],{"class":1120},"¥16,800",[793,1371,1117],{"class":799},[793,1373,1238],{"class":799},[793,1375,1377],{"class":795,"line":1376},30,[793,1378,1379],{"class":799},"                },\n",[793,1381,1383,1386,1388,1391,1393,1396,1398,1401,1403,1405,1407,1410],{"class":795,"line":1382},31,[793,1384,1385],{"class":921},"                template",[793,1387,931],{"class":799},[793,1389,1390],{"class":908},"ColumnWidths",[793,1392,951],{"class":799},[793,1394,1395],{"class":995},"50",[793,1397,1082],{"class":799},[793,1399,1400],{"class":995}," 15",[793,1402,1082],{"class":799},[793,1404,1400],{"class":995},[793,1406,1082],{"class":799},[793,1408,1409],{"class":995}," 20",[793,1411,962],{"class":799},[793,1413,1415,1417,1419,1422],{"class":795,"line":1414},32,[793,1416,1385],{"class":921},[793,1418,931],{"class":799},[793,1420,1421],{"class":908},"TableHeaderStyle",[793,1423,937],{"class":799},[793,1425,1427,1430,1432,1434],{"class":795,"line":1426},33,[793,1428,1429],{"class":921},"                    template",[793,1431,931],{"class":799},[793,1433,1133],{"class":908},[793,1435,1436],{"class":799},"(),\n",[793,1438,1440,1442,1444,1447,1449,1452,1454,1457],{"class":795,"line":1439},34,[793,1441,1429],{"class":921},[793,1443,931],{"class":799},[793,1445,1446],{"class":908},"TextColor",[793,1448,951],{"class":799},[793,1450,1451],{"class":921},"pdf",[793,1453,931],{"class":799},[793,1455,1456],{"class":921},"White",[793,1458,962],{"class":799},[793,1460,1462,1464,1466,1469,1471,1473,1475,1478,1480,1483],{"class":795,"line":1461},35,[793,1463,1429],{"class":921},[793,1465,931],{"class":799},[793,1467,1468],{"class":908},"BgColor",[793,1470,951],{"class":799},[793,1472,1451],{"class":921},[793,1474,931],{"class":799},[793,1476,1477],{"class":908},"RGBHex",[793,1479,951],{"class":799},[793,1481,1482],{"class":995},"0x1A237E",[793,1484,1485],{"class":799},")),\n",[793,1487,1489],{"class":795,"line":1488},36,[793,1490,1491],{"class":799},"                ),\n",[793,1493,1495],{"class":795,"line":1494},37,[793,1496,1497],{"class":799},"            )\n",[793,1499,1501],{"class":795,"line":1500},38,[793,1502,1503],{"class":799},"        })\n",[793,1505,1507],{"class":795,"line":1506},39,[793,1508,1509],{"class":799},"    })\n",[793,1511,1513],{"class":795,"line":1512},40,[793,1514,811],{"emptyLinePlaceholder":810},[793,1516,1518,1521,1523,1526,1528,1530,1532,1535],{"class":795,"line":1517},41,[793,1519,1520],{"class":921},"    data",[793,1522,1082],{"class":799},[793,1524,1525],{"class":921}," err ",[793,1527,925],{"class":799},[793,1529,1021],{"class":921},[793,1531,931],{"class":799},[793,1533,1534],{"class":908},"Generate",[793,1536,1029],{"class":799},[793,1538,1540,1543,1545,1548,1551],{"class":795,"line":1539},42,[793,1541,1542],{"class":817},"    if",[793,1544,1525],{"class":921},[793,1546,1547],{"class":799},"!=",[793,1549,1550],{"class":799}," nil",[793,1552,915],{"class":799},[793,1554,1556,1559,1561,1564,1566,1569],{"class":795,"line":1555},43,[793,1557,1558],{"class":921},"        log",[793,1560,931],{"class":799},[793,1562,1563],{"class":908},"Fatal",[793,1565,951],{"class":799},[793,1567,1568],{"class":921},"err",[793,1570,894],{"class":799},[793,1572,1574],{"class":795,"line":1573},44,[793,1575,1576],{"class":799},"    }\n",[793,1578,1580,1582,1584,1586,1589,1591,1594,1596,1598,1601,1603,1605,1608,1610,1613,1616,1618,1620,1622],{"class":795,"line":1579},45,[793,1581,1542],{"class":817},[793,1583,1525],{"class":921},[793,1585,925],{"class":799},[793,1587,1588],{"class":921}," os",[793,1590,931],{"class":799},[793,1592,1593],{"class":908},"WriteFile",[793,1595,951],{"class":799},[793,1597,1117],{"class":799},[793,1599,1600],{"class":1120},"invoice.pdf",[793,1602,1117],{"class":799},[793,1604,1082],{"class":799},[793,1606,1607],{"class":921}," data",[793,1609,1082],{"class":799},[793,1611,1612],{"class":995}," 0o644",[793,1614,1615],{"class":799},");",[793,1617,1525],{"class":921},[793,1619,1547],{"class":799},[793,1621,1550],{"class":799},[793,1623,915],{"class":799},[793,1625,1627,1629,1631,1633,1635,1637],{"class":795,"line":1626},46,[793,1628,1558],{"class":921},[793,1630,931],{"class":799},[793,1632,1563],{"class":908},[793,1634,951],{"class":799},[793,1636,1568],{"class":921},[793,1638,894],{"class":799},[793,1640,1642],{"class":795,"line":1641},47,[793,1643,1576],{"class":799},[793,1645,1647],{"class":795,"line":1646},48,[793,1648,1649],{"class":799},"}\n",[18,1651,1652,1653,1656,1657,1660],{},"零 ",[55,1654,1655],{},"SetXY","。零手动列宽计算。给文档选项加 ",[55,1658,1659],{},"gpdf.WithFont(\"NotoSansCJK\", ttfBytes)","，上面的中文就能正常渲染，不会变豆腐。",[13,1662,1663],{"id":1663},"未纳入的部分",[18,1665,1666],{},"每篇比较都有\"因为 X 而未纳入\"的小节。我们的：",[27,1668,1669,1675,1687,1697],{},[30,1670,1671,1674],{},[22,1672,1673],{},"私有 gofpdf fork","。确实存在在生产里的内部 fork。看不到的代码无法基准。",[30,1676,1677,1682,1683,1686],{},[22,1678,1679],{},[55,1680,1681],{},"pdfcpu","。常在\"Go PDF 库\"列表里出现，但主用途是 ",[22,1684,1685],{},"PDF 处理器","（合并、拆分、加密、盖章），不是生成。超出本文范围，会单写一篇处理向的文章。",[30,1688,1689,1696],{},[22,1690,1691,1692,1695],{},"任何包装 ",[55,1693,1694],{},"gotenberg"," 或 headless 浏览器服务的","。不是库，比较不公平。",[30,1698,1699,1705],{},[22,1700,1701,1702,1704],{},"我们自家的 ",[55,1703,93],{}," 基准","。本次比较的焦点是核心数字。",[13,1707,1709],{"id":1708},"faq","FAQ",[18,1711,1712,1715],{},[22,1713,1714],{},"gpdf 为什么比 gofpdf 快 10 倍？是不是有魔法？","\n没有单一魔法。3 个设计叠加：单遍布局（构建器到写入器之间无 AST）、热路径用具体类型、cmap 缓存的 TrueType 子集器。任一单独提供 2× 收益，叠起来是数量级差异。",[18,1717,1718,1721,1722,1725],{},[22,1719,1720],{},"能自己复现这个基准吗？","\n能。",[55,1723,1724],{},"git clone https://github.com/gpdf-dev/gpdf && cd gpdf/_benchmark && go test -bench=. -benchmem","。相同 CPU 架构、相同 Go 版本下数字对不上，请开 issue。基准漂移会发生，我们想知道。",[18,1727,1728,1731],{},[22,1729,1730],{},"gofpdf 会回来吗？","\n现实地讲，不会。最后一次提交是 2021 年。issue tracker 已关闭。即使有人重新打开，游标 + 单字节字体 + 无栅格的架构不是 2026 年合适的起点。当作历史文物、直接迁移更实际。",[18,1733,1734,1737],{},[22,1735,1736],{},"Java iText / Python ReportLab / Node pdfkit 呢？","\n跨语言基准是另一篇。简短版：Go 在吞吐和冷启动上通常赢，在功能广度（尤其 HTML→PDF 保真度）上输。已在 Go 的团队用 gpdf 更快、更小；Python / Node 团队迁移成本高，只有在大流量场景才划算。",[18,1739,1740,1743],{},[22,1741,1742],{},"如果 gpdf 的竞争对手变强，这份对比会保持公平吗？","\n会。每年跑一次。若 signintech/gopdf 推出表格 API 把时间减半，2027 版会写进去。若 Maroto v2 替换完 gofpdf，那一行会改。基准代码故意公开，不用任何人相信我们。",[13,1745,1747],{"id":1746},"试试-gpdf","试试 gpdf",[18,1749,1750],{},"gpdf 是 Go 的 PDF 生成库。MIT、零依赖、原生 CJK。",[784,1752,1756],{"className":1753,"code":1754,"language":1755,"meta":789,"style":789},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[55,1757,1758],{"__ignoreMap":789},[793,1759,1760,1762,1765],{"class":795,"line":796},[793,1761,788],{"class":803},[793,1763,1764],{"class":1120}," get",[793,1766,1767],{"class":1120}," github.com/gpdf-dev/gpdf\n",[18,1769,1770,1775,1776],{},[317,1771,1774],{"href":1772,"rel":1773},"https://github.com/gpdf-dev/gpdf",[321],"⭐ 在 GitHub 点星"," · ",[317,1777,1780],{"href":1778,"rel":1779},"https://gpdf.dev/zh/docs/quickstart",[321],"阅读文档",[13,1782,1783],{"id":1783},"下一步阅读",[27,1785,1786,1792,1803],{},[30,1787,1788,1791],{},[317,1789,1790],{"href":719},"gofpdf 已归档：迁移到 gpdf 的完整指南"," —— 完整 API 映射 + 5 组 Before/After 代码。",[30,1793,1794,1798,1799,1802],{},[317,1795,1797],{"href":1778,"rel":1796},[321],"Quickstart"," —— 含 ",[55,1800,1801],{},"go.mod"," 的 5 分钟上手。",[30,1804,1805,1806,81],{},"基准代码本身：",[317,1807,1809],{"href":319,"rel":1808},[321],[55,1810,57],{},[1812,1813,1814],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":789,"searchDepth":807,"depth":807,"links":1816},[1817,1818,1819,1820,1824,1825,1826,1827,1828,1829,1830,1831,1832],{"id":15,"depth":807,"text":16},{"id":61,"depth":807,"text":62},{"id":111,"depth":807,"text":111},{"id":312,"depth":807,"text":312,"children":1821},[1822,1823],{"id":367,"depth":814,"text":367},{"id":487,"depth":814,"text":487},{"id":525,"depth":807,"text":525},{"id":133,"depth":807,"text":133},{"id":684,"depth":807,"text":684},{"id":728,"depth":807,"text":728},{"id":778,"depth":807,"text":779},{"id":1663,"depth":807,"text":1663},{"id":1708,"depth":807,"text":1709},{"id":1746,"depth":807,"text":1747},{"id":1783,"depth":807,"text":1783},"2026-04-15","2026 年仍在维护的 Go PDF 库，在 4 种工作负载上基准测试，并对比许可证、依赖与维护状态。",false,"md",null,{},"/zh/blog/go-pdf-library-showdown-2026",{"title":5,"description":1834},"zh/blog/002.go-pdf-library-showdown-2026",[1843,1844],"comparison","benchmark","yXXt1Esago0CnHoFxknEwym8EOoHrbkdoxqhMvutRrA",1776529262321]