[{"data":1,"prerenderedAt":5099},["ShallowReactive",2],{"blog-zh-gofpdf-migration":3},{"id":4,"title":5,"author":6,"body":9,"date":5060,"description":5061,"draft":5062,"extension":5063,"howTo":5064,"image":5088,"meta":5089,"navigation":507,"path":5090,"seo":5091,"stem":5092,"tags":5093,"updated":5088,"__hash__":5098},"blogZh/zh/blog/001.gofpdf-migration.md","gofpdf 已归档：迁移到 gpdf 的完整指南",{"name":7,"url":8},"gpdf team","https://gpdf.dev",{"type":10,"value":11,"toc":5044},"minimark",[12,17,38,49,52,66,69,73,79,82,89,96,99,103,106,134,140,144,147,426,440,468,472,475,480,712,717,1181,1191,1205,1209,1219,1223,1972,1975,1979,2360,2377,2380,2384,2390,2394,2557,2570,2574,3027,3030,3041,3044,3047,3051,3072,3076,3398,3404,3408,4085,4101,4105,4119,4123,4401,4405,4725,4741,4745,4755,4851,4854,4857,4860,4863,4903,4906,4910,4916,4938,4948,4960,4969,4975,4979,4982,4999,5014,5017,5040],[13,14,16],"h2",{"id":15},"tldr","TL;DR",[18,19,20,24,25,29,30,33,34,37],"p",{},[21,22,23],"strong",{},"gpdf"," 是一个纯 Go、零外部依赖的 PDF 生成库，原生支持 CJK（无需 ",[26,27,28],"code",{},"AddUTF8Font"," 那套繁琐流程），用 12 栅格替代 ",[26,31,32],{},"SetXY"," 的像素级定位，在相同负载下 ",[21,35,36],{},"比 gofpdf 快约 10 倍","。迁移的核心是把命令式的游标调用换成声明式的构建器。本文用 5 组 Before/After 示例讲完整个映射。",[18,39,40,41,44,45,48],{},"上周一位同事开了个新 Go 项目，跑了 ",[26,42,43],{},"go get github.com/jung-kurt/gofpdf","，10 分钟后发来 GitHub 的横幅截图：",[21,46,47],{},"\"This repository has been archived by the owner. It is now read-only.\""," 接着一句：\"等等，那个 fork 也归档了？\"",[18,50,51],{},"是的，两个都归档了。",[18,53,54,57,58,61,62,65],{},[26,55,56],{},"jung-kurt/gofpdf"," 于 ",[21,59,60],{},"2021 年 9 月 8 日"," 归档。社区 fork ",[26,63,64],{},"go-pdf/fpdf"," 最后一次发版是 2023 年，2025 年正式归档。Stack Overflow 和中文博客上约三分之二的 Go PDF 答案仍然指向 gofpdf，但它已经只读 4 年多，连接棒者也消失了。",[18,67,68],{},"如果你的 gofpdf 代码已经在生产，这篇是迁移地图。如果你正新开项目因为搜索结果推 gofpdf 而反手就装，这篇就是替代方案。",[13,70,72],{"id":71},"为什么-gofpdf-真的复活不了","为什么 gofpdf 真的复活不了",[18,74,75,76,78],{},"开源库不一定会死。有时原维护者退出，有人接手。大家都以为 gofpdf 会这样 —— 一段时间内也的确如此。",[26,77,64],{}," 重新整理了代码、修了几个老 bug、接受 PR，看起来像真正的延续。",[18,80,81],{},"但 2025 年初，fork 也归档了。README 写着：\"该项目不再积极维护，请考虑使用其他库。\"",[18,83,84,85,88],{},"原因不重要，结果才重要：",[21,86,87],{},"所有依赖 gofpdf 的 Go 项目，现在都坐在两层无人维护的代码之上","。安全漏洞不会被修复。PDF 2.0 规范 2020 年发布，gofpdf 大部分都没跟进。Go 1.25 的循环变量语义现在还能和 gofpdf 配合，但明天坏了的话只能自己维护一个 fork。",[18,90,91,92,95],{},"这不是\"这个库有 bug\"的问题，是",[21,93,94],{},"供应链","的问题。",[18,97,98],{},"对中国团队尤其重要 —— 电子发票、增值税凭证、合规归档，拿一个未维护的库当技术栈基础，难以通过审计。",[13,100,102],{"id":101},"中文团队用-gofpdf-都在做什么","中文团队用 gofpdf 都在做什么",[18,104,105],{},"翻 GitHub Issues 和中文社区的提问，gofpdf 的主要用途集中在：",[107,108,109,116,122,128],"ol",{},[110,111,112,115],"li",{},[21,113,114],{},"发票、收据、送货单"," —— 页眉、客户信息、明细表、合计、页脚",[110,117,118,121],{},[21,119,120],{},"报表"," —— 重复页眉页脚、页码、图表（以图像形式插入）的多页文档",[110,123,124,127],{},[21,125,126],{},"证书和表单"," —— 固定位置文字叠加在模板之上",[110,129,130,133],{},[21,131,132],{},"CJK 文档"," —— 中日韩文发票和物流标签",[18,135,136,137,139],{},"前三类 gpdf 的 builder API 都能直接覆盖。第四类 CJK 才是 gpdf 相对 gofpdf 最大的差距 —— gofpdf 要求调用 ",[26,138,28],{},"，管理 TTF 文件路径，并祈祷你的文本不会超出基本字符面。gpdf 从设计之初就把 CJK 当作一等公民：注册 TrueType 字体，写中文，输出 PDF。",[13,141,143],{"id":142},"api-对照表","API 对照表",[18,145,146],{},"下表是速查表。后面章节逐个讲 5 组具体的 Before/After。",[148,149,150,165],"table",{},[151,152,153],"thead",{},[154,155,156,160,163],"tr",{},[157,158,159],"th",{},"你想做什么",[157,161,162],{},"gofpdf",[157,164,23],{},[166,167,168,184,208,230,248,263,281,299,314,329,347,362,377,396,411],"tbody",{},[154,169,170,174,179],{},[171,172,173],"td",{},"创建文档",[171,175,176],{},[26,177,178],{},"gofpdf.New(\"P\", \"mm\", \"A4\", \"\")",[171,180,181],{},[26,182,183],{},"gpdf.NewDocument(gpdf.WithPageSize(document.A4))",[154,185,186,189,194],{},[171,187,188],{},"添加页面",[171,190,191],{},[26,192,193],{},"pdf.AddPage()",[171,195,196,199,200],{},[26,197,198],{},"doc.AddPage()"," ",[201,202,203,204,207],"em",{},"(返回 ",[26,205,206],{},"*PageBuilder",")",[154,209,210,213,218],{},[171,211,212],{},"设置字体",[171,214,215],{},[26,216,217],{},"pdf.SetFont(\"Arial\", \"B\", 16)",[171,219,220,223,224,223,227],{},[26,221,222],{},"template.FontFamily(...)"," / ",[26,225,226],{},"template.Bold()",[26,228,229],{},"template.FontSize(16)",[154,231,232,235,240],{},[171,233,234],{},"注册 TTF (CJK)",[171,236,237],{},[26,238,239],{},"pdf.AddUTF8Font(\"noto\", \"\", \"NotoSansSC-Regular.ttf\")",[171,241,242,199,245],{},[26,243,244],{},"gpdf.WithFont(\"NotoSansSC\", ttfBytes)",[201,246,247],{},"(构造时传入)",[154,249,250,253,258],{},[171,251,252],{},"写单行文本",[171,254,255],{},[26,256,257],{},"pdf.Cell(40, 10, \"hi\")",[171,259,260],{},[26,261,262],{},"c.Text(\"hi\")",[154,264,265,268,273],{},[171,266,267],{},"写自动换行文本",[171,269,270],{},[26,271,272],{},"pdf.MultiCell(0, 10, body, \"\", \"L\", false)",[171,274,275,199,278],{},[26,276,277],{},"c.Text(body)",[201,279,280],{},"(自动换行)",[154,282,283,286,291],{},[171,284,285],{},"设置文字颜色",[171,287,288],{},[26,289,290],{},"pdf.SetTextColor(255, 0, 0)",[171,292,293,199,296],{},[26,294,295],{},"template.TextColor(pdf.Red)",[201,297,298],{},"(per-text 选项)",[154,300,301,304,309],{},[171,302,303],{},"画横线",[171,305,306],{},[26,307,308],{},"pdf.Line(x1, y1, x2, y2)",[171,310,311],{},[26,312,313],{},"c.Line(template.LineThickness(document.Pt(1)))",[154,315,316,319,324],{},[171,317,318],{},"嵌入图像",[171,320,321],{},[26,322,323],{},"pdf.ImageOptions(\"logo.png\", x, y, w, h, ...)",[171,325,326],{},[26,327,328],{},"c.Image(imgBytes, template.FitWidth(document.Mm(50)))",[154,330,331,334,339],{},[171,332,333],{},"设置光标坐标",[171,335,336],{},[26,337,338],{},"pdf.SetXY(x, y)",[171,340,341],{},[201,342,343,344,207],{},"(无对应 —— 用行/列，或 ",[26,345,346],{},"page.Absolute(x, y, fn)",[154,348,349,352,357],{},[171,350,351],{},"每页重复页眉",[171,353,354],{},[26,355,356],{},"pdf.SetHeaderFunc(fn)",[171,358,359],{},[26,360,361],{},"doc.Header(fn)",[154,363,364,367,372],{},[171,365,366],{},"每页重复页脚",[171,368,369],{},[26,370,371],{},"pdf.SetFooterFunc(fn)",[171,373,374],{},[26,375,376],{},"doc.Footer(fn)",[154,378,379,382,388],{},[171,380,381],{},"页码",[171,383,384,387],{},[26,385,386],{},"pdf.PageNo()","（手动）",[171,389,390,223,393],{},[26,391,392],{},"c.PageNumber()",[26,394,395],{},"c.TotalPages()",[154,397,398,401,406],{},[171,399,400],{},"输出到文件",[171,402,403],{},[26,404,405],{},"pdf.OutputFileAndClose(\"out.pdf\")",[171,407,408],{},[26,409,410],{},"data, _ := doc.Generate(); os.WriteFile(\"out.pdf\", data, 0o644)",[154,412,413,416,421],{},[171,414,415],{},"输出到 Writer",[171,417,418],{},[26,419,420],{},"pdf.Output(w)",[171,422,423],{},[26,424,425],{},"doc.Render(w)",[18,427,428,429,432,433,436,437,439],{},"最大的变化是 API 形态：gofpdf 是",[21,430,431],{},"命令式","，gpdf 是",[21,434,435],{},"声明式","。gofpdf 里你推着光标走，光标到哪写到哪。gpdf 里你描述一棵由行与列组成的树，布局引擎负责摆放。前几段代码 gpdf 写起来感觉更长。写到第三个，你就不再想念 ",[26,438,32],{}," 了。",[18,441,442,443,223,446,223,449,452,453,456,457,456,460,463,464,467],{},"关于单位。gofpdf 构造时选一种基准单位（",[26,444,445],{},"\"mm\"",[26,447,448],{},"\"pt\"",[26,450,451],{},"\"in\"","），之后都按那个来。gpdf 内部统一用 pt，调用时用 ",[26,454,455],{},"document.Mm(20)","、",[26,458,459],{},"document.Pt(12)",[26,461,462],{},"document.Cm(1)"," 等帮助函数，按场景选单位。这更像 CSS 的思路，一旦用 ",[26,465,466],{},"document.Mm(15)"," 定好页边距，就不再需要操心单位的事。",[13,469,471],{"id":470},"before-after-1最简单的-pdf","Before / After 1：最简单的 PDF",[18,473,474],{},"\"hello world\" 对。gofpdf 的简洁是它流行的原因之一。gpdf 版本多几行，因为它在构建一棵树，不是驱动光标。",[18,476,477],{},[21,478,479],{},"Before — gofpdf:",[481,482,487],"pre",{"className":483,"code":484,"language":485,"meta":486,"style":486},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","package main\n\nimport \"github.com/jung-kurt/gofpdf\"\n\nfunc main() {\n    pdf := gofpdf.New(\"P\", \"mm\", \"A4\", \"\")\n    pdf.AddPage()\n    pdf.SetFont(\"Arial\", \"B\", 24)\n    pdf.Cell(40, 10, \"Hello, World!\")\n    pdf.OutputFileAndClose(\"hello.pdf\")\n}\n","go","",[26,488,489,502,509,525,530,546,604,618,654,685,706],{"__ignoreMap":486},[490,491,494,498],"span",{"class":492,"line":493},"line",1,[490,495,497],{"class":496},"sMK4o","package",[490,499,501],{"class":500},"sBMFI"," main\n",[490,503,505],{"class":492,"line":504},2,[490,506,508],{"emptyLinePlaceholder":507},true,"\n",[490,510,512,516,519,522],{"class":492,"line":511},3,[490,513,515],{"class":514},"s7zQu","import",[490,517,518],{"class":496}," \"",[490,520,521],{"class":500},"github.com/jung-kurt/gofpdf",[490,523,524],{"class":496},"\"\n",[490,526,528],{"class":492,"line":527},4,[490,529,508],{"emptyLinePlaceholder":507},[490,531,533,536,540,543],{"class":492,"line":532},5,[490,534,535],{"class":496},"func",[490,537,539],{"class":538},"s2Zo4"," main",[490,541,542],{"class":496},"()",[490,544,545],{"class":496}," {\n",[490,547,549,553,556,559,562,565,568,571,575,577,580,582,585,587,589,591,594,596,598,601],{"class":492,"line":548},6,[490,550,552],{"class":551},"sTEyZ","    pdf ",[490,554,555],{"class":496},":=",[490,557,558],{"class":551}," gofpdf",[490,560,561],{"class":496},".",[490,563,564],{"class":538},"New",[490,566,567],{"class":496},"(",[490,569,570],{"class":496},"\"",[490,572,574],{"class":573},"sfazB","P",[490,576,570],{"class":496},[490,578,579],{"class":496},",",[490,581,518],{"class":496},[490,583,584],{"class":573},"mm",[490,586,570],{"class":496},[490,588,579],{"class":496},[490,590,518],{"class":496},[490,592,593],{"class":573},"A4",[490,595,570],{"class":496},[490,597,579],{"class":496},[490,599,600],{"class":496}," \"\"",[490,602,603],{"class":496},")\n",[490,605,607,610,612,615],{"class":492,"line":606},7,[490,608,609],{"class":551},"    pdf",[490,611,561],{"class":496},[490,613,614],{"class":538},"AddPage",[490,616,617],{"class":496},"()\n",[490,619,621,623,625,628,630,632,635,637,639,641,644,646,648,652],{"class":492,"line":620},8,[490,622,609],{"class":551},[490,624,561],{"class":496},[490,626,627],{"class":538},"SetFont",[490,629,567],{"class":496},[490,631,570],{"class":496},[490,633,634],{"class":573},"Arial",[490,636,570],{"class":496},[490,638,579],{"class":496},[490,640,518],{"class":496},[490,642,643],{"class":573},"B",[490,645,570],{"class":496},[490,647,579],{"class":496},[490,649,651],{"class":650},"sbssI"," 24",[490,653,603],{"class":496},[490,655,657,659,661,664,666,669,671,674,676,678,681,683],{"class":492,"line":656},9,[490,658,609],{"class":551},[490,660,561],{"class":496},[490,662,663],{"class":538},"Cell",[490,665,567],{"class":496},[490,667,668],{"class":650},"40",[490,670,579],{"class":496},[490,672,673],{"class":650}," 10",[490,675,579],{"class":496},[490,677,518],{"class":496},[490,679,680],{"class":573},"Hello, World!",[490,682,570],{"class":496},[490,684,603],{"class":496},[490,686,688,690,692,695,697,699,702,704],{"class":492,"line":687},10,[490,689,609],{"class":551},[490,691,561],{"class":496},[490,693,694],{"class":538},"OutputFileAndClose",[490,696,567],{"class":496},[490,698,570],{"class":496},[490,700,701],{"class":573},"hello.pdf",[490,703,570],{"class":496},[490,705,603],{"class":496},[490,707,709],{"class":492,"line":708},11,[490,710,711],{"class":496},"}\n",[18,713,714],{},[21,715,716],{},"After — gpdf:",[481,718,720],{"className":483,"code":719,"language":485,"meta":486,"style":486},"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/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(\"Hello, World!\", template.FontSize(24), template.Bold())\n        })\n    })\n\n    data, err := doc.Generate()\n    if err != nil {\n        log.Fatal(err)\n    }\n    if err := os.WriteFile(\"hello.pdf\", data, 0o644); err != nil {\n        log.Fatal(err)\n    }\n}\n",[26,721,722,728,732,739,749,758,762,771,780,789,793,797,808,827,850,886,892,897,914,947,984,1031,1037,1043,1048,1070,1086,1104,1110,1156,1171,1176],{"__ignoreMap":486},[490,723,724,726],{"class":492,"line":493},[490,725,497],{"class":496},[490,727,501],{"class":500},[490,729,730],{"class":492,"line":504},[490,731,508],{"emptyLinePlaceholder":507},[490,733,734,736],{"class":492,"line":511},[490,735,515],{"class":514},[490,737,738],{"class":496}," (\n",[490,740,741,744,747],{"class":492,"line":527},[490,742,743],{"class":496},"    \"",[490,745,746],{"class":500},"log",[490,748,524],{"class":496},[490,750,751,753,756],{"class":492,"line":532},[490,752,743],{"class":496},[490,754,755],{"class":500},"os",[490,757,524],{"class":496},[490,759,760],{"class":492,"line":548},[490,761,508],{"emptyLinePlaceholder":507},[490,763,764,766,769],{"class":492,"line":606},[490,765,743],{"class":496},[490,767,768],{"class":500},"github.com/gpdf-dev/gpdf",[490,770,524],{"class":496},[490,772,773,775,778],{"class":492,"line":620},[490,774,743],{"class":496},[490,776,777],{"class":500},"github.com/gpdf-dev/gpdf/document",[490,779,524],{"class":496},[490,781,782,784,787],{"class":492,"line":656},[490,783,743],{"class":496},[490,785,786],{"class":500},"github.com/gpdf-dev/gpdf/template",[490,788,524],{"class":496},[490,790,791],{"class":492,"line":687},[490,792,603],{"class":496},[490,794,795],{"class":492,"line":708},[490,796,508],{"emptyLinePlaceholder":507},[490,798,800,802,804,806],{"class":492,"line":799},12,[490,801,535],{"class":496},[490,803,539],{"class":538},[490,805,542],{"class":496},[490,807,545],{"class":496},[490,809,811,814,816,819,821,824],{"class":492,"line":810},13,[490,812,813],{"class":551},"    doc ",[490,815,555],{"class":496},[490,817,818],{"class":551}," gpdf",[490,820,561],{"class":496},[490,822,823],{"class":538},"NewDocument",[490,825,826],{"class":496},"(\n",[490,828,830,833,835,838,840,843,845,847],{"class":492,"line":829},14,[490,831,832],{"class":551},"        gpdf",[490,834,561],{"class":496},[490,836,837],{"class":538},"WithPageSize",[490,839,567],{"class":496},[490,841,842],{"class":551},"document",[490,844,561],{"class":496},[490,846,593],{"class":551},[490,848,849],{"class":496},"),\n",[490,851,853,855,857,860,862,864,866,869,871,873,875,878,880,883],{"class":492,"line":852},15,[490,854,832],{"class":551},[490,856,561],{"class":496},[490,858,859],{"class":538},"WithMargins",[490,861,567],{"class":496},[490,863,842],{"class":551},[490,865,561],{"class":496},[490,867,868],{"class":538},"UniformEdges",[490,870,567],{"class":496},[490,872,842],{"class":551},[490,874,561],{"class":496},[490,876,877],{"class":538},"Mm",[490,879,567],{"class":496},[490,881,882],{"class":650},"20",[490,884,885],{"class":496},"))),\n",[490,887,889],{"class":492,"line":888},16,[490,890,891],{"class":496},"    )\n",[490,893,895],{"class":492,"line":894},17,[490,896,508],{"emptyLinePlaceholder":507},[490,898,900,903,905,908,910,912],{"class":492,"line":899},18,[490,901,902],{"class":551},"    page ",[490,904,555],{"class":496},[490,906,907],{"class":551}," doc",[490,909,561],{"class":496},[490,911,614],{"class":538},[490,913,617],{"class":496},[490,915,917,920,922,925,928,932,935,938,940,943,945],{"class":492,"line":916},19,[490,918,919],{"class":551},"    page",[490,921,561],{"class":496},[490,923,924],{"class":538},"AutoRow",[490,926,927],{"class":496},"(func(",[490,929,931],{"class":930},"sHdIc","r",[490,933,934],{"class":496}," *",[490,936,937],{"class":500},"template",[490,939,561],{"class":496},[490,941,942],{"class":500},"RowBuilder",[490,944,207],{"class":496},[490,946,545],{"class":496},[490,948,950,953,955,958,960,963,965,968,971,973,975,977,980,982],{"class":492,"line":949},20,[490,951,952],{"class":551},"        r",[490,954,561],{"class":496},[490,956,957],{"class":538},"Col",[490,959,567],{"class":496},[490,961,962],{"class":650},"12",[490,964,579],{"class":496},[490,966,967],{"class":496}," func(",[490,969,970],{"class":930},"c",[490,972,934],{"class":496},[490,974,937],{"class":500},[490,976,561],{"class":496},[490,978,979],{"class":500},"ColBuilder",[490,981,207],{"class":496},[490,983,545],{"class":496},[490,985,987,990,992,995,997,999,1001,1003,1005,1008,1010,1013,1015,1018,1021,1023,1025,1028],{"class":492,"line":986},21,[490,988,989],{"class":551},"            c",[490,991,561],{"class":496},[490,993,994],{"class":538},"Text",[490,996,567],{"class":496},[490,998,570],{"class":496},[490,1000,680],{"class":573},[490,1002,570],{"class":496},[490,1004,579],{"class":496},[490,1006,1007],{"class":551}," template",[490,1009,561],{"class":496},[490,1011,1012],{"class":538},"FontSize",[490,1014,567],{"class":496},[490,1016,1017],{"class":650},"24",[490,1019,1020],{"class":496},"),",[490,1022,1007],{"class":551},[490,1024,561],{"class":496},[490,1026,1027],{"class":538},"Bold",[490,1029,1030],{"class":496},"())\n",[490,1032,1034],{"class":492,"line":1033},22,[490,1035,1036],{"class":496},"        })\n",[490,1038,1040],{"class":492,"line":1039},23,[490,1041,1042],{"class":496},"    })\n",[490,1044,1046],{"class":492,"line":1045},24,[490,1047,508],{"emptyLinePlaceholder":507},[490,1049,1051,1054,1056,1059,1061,1063,1065,1068],{"class":492,"line":1050},25,[490,1052,1053],{"class":551},"    data",[490,1055,579],{"class":496},[490,1057,1058],{"class":551}," err ",[490,1060,555],{"class":496},[490,1062,907],{"class":551},[490,1064,561],{"class":496},[490,1066,1067],{"class":538},"Generate",[490,1069,617],{"class":496},[490,1071,1073,1076,1078,1081,1084],{"class":492,"line":1072},26,[490,1074,1075],{"class":514},"    if",[490,1077,1058],{"class":551},[490,1079,1080],{"class":496},"!=",[490,1082,1083],{"class":496}," nil",[490,1085,545],{"class":496},[490,1087,1089,1092,1094,1097,1099,1102],{"class":492,"line":1088},27,[490,1090,1091],{"class":551},"        log",[490,1093,561],{"class":496},[490,1095,1096],{"class":538},"Fatal",[490,1098,567],{"class":496},[490,1100,1101],{"class":551},"err",[490,1103,603],{"class":496},[490,1105,1107],{"class":492,"line":1106},28,[490,1108,1109],{"class":496},"    }\n",[490,1111,1113,1115,1117,1119,1122,1124,1127,1129,1131,1133,1135,1137,1140,1142,1145,1148,1150,1152,1154],{"class":492,"line":1112},29,[490,1114,1075],{"class":514},[490,1116,1058],{"class":551},[490,1118,555],{"class":496},[490,1120,1121],{"class":551}," os",[490,1123,561],{"class":496},[490,1125,1126],{"class":538},"WriteFile",[490,1128,567],{"class":496},[490,1130,570],{"class":496},[490,1132,701],{"class":573},[490,1134,570],{"class":496},[490,1136,579],{"class":496},[490,1138,1139],{"class":551}," data",[490,1141,579],{"class":496},[490,1143,1144],{"class":650}," 0o644",[490,1146,1147],{"class":496},");",[490,1149,1058],{"class":551},[490,1151,1080],{"class":496},[490,1153,1083],{"class":496},[490,1155,545],{"class":496},[490,1157,1159,1161,1163,1165,1167,1169],{"class":492,"line":1158},30,[490,1160,1091],{"class":551},[490,1162,561],{"class":496},[490,1164,1096],{"class":538},[490,1166,567],{"class":496},[490,1168,1101],{"class":551},[490,1170,603],{"class":496},[490,1172,1174],{"class":492,"line":1173},31,[490,1175,1109],{"class":496},[490,1177,1179],{"class":492,"line":1178},32,[490,1180,711],{"class":496},[18,1182,1183,1184,1186,1187,1190],{},"栅格替你干活。",[26,1185,924],{}," 添加一个高度由内容决定的行，",[26,1188,1189],{},"r.Col(12, ...)"," 表示\"这列占满 12 栅格\"。就是 Bootstrap 思路搬到 PDF 页面上。",[18,1192,1193,1196,1197,1200,1201,1204],{},[26,1194,1195],{},"Generate()"," 返回字节切片；",[26,1198,1199],{},"Render(w)"," 流式写入 ",[26,1202,1203],{},"io.Writer","，避免分配。没有\"关闭文件\"一步，因为 gpdf 不持有文件句柄。",[13,1206,1208],{"id":1207},"before-after-2发票明细表","Before / After 2：发票明细表",[18,1210,1211,1212,1214,1215,1218],{},"表格是 gofpdf 最啰嗦的地方。它没有内建表格，你得在嵌套循环里调 ",[26,1213,663],{},"，自己算列宽，用 ",[26,1216,1217],{},"Ln(-1)"," 换行。网上一半的 gofpdf 发票教程，代码量都耗在了表格样板上。",[18,1220,1221],{},[21,1222,479],{},[481,1224,1226],{"className":483,"code":1225,"language":485,"meta":486,"style":486},"pdf.SetFont(\"Arial\", \"B\", 11)\npdf.SetFillColor(220, 220, 220)\npdf.CellFormat(80, 8, \"品名\",   \"1\", 0, \"L\", true, 0, \"\")\npdf.CellFormat(20, 8, \"数量\",   \"1\", 0, \"C\", true, 0, \"\")\npdf.CellFormat(30, 8, \"单价\",   \"1\", 0, \"R\", true, 0, \"\")\npdf.CellFormat(30, 8, \"金额\",   \"1\", 1, \"R\", true, 0, \"\")\n\npdf.SetFont(\"Arial\", \"\", 11)\nitems := [][]string{\n    {\"前端开发\", \"40h\", \"¥1,500\", \"¥60,000\"},\n    {\"后端开发\", \"60h\", \"¥1,500\", \"¥90,000\"},\n    {\"UI 设计\", \"20h\", \"¥1,200\", \"¥24,000\"},\n}\nfor _, row := range items {\n    pdf.CellFormat(80, 8, row[0], \"1\", 0, \"L\", false, 0, \"\")\n    pdf.CellFormat(20, 8, row[1], \"1\", 0, \"C\", false, 0, \"\")\n    pdf.CellFormat(30, 8, row[2], \"1\", 0, \"R\", false, 0, \"\")\n    pdf.CellFormat(30, 8, row[3], \"1\", 1, \"R\", false, 0, \"\")\n}\n",[26,1227,1228,1260,1285,1353,1413,1474,1534,1538,1564,1581,1623,1662,1702,1706,1729,1792,1850,1909,1968],{"__ignoreMap":486},[490,1229,1230,1233,1235,1237,1239,1241,1243,1245,1247,1249,1251,1253,1255,1258],{"class":492,"line":493},[490,1231,1232],{"class":551},"pdf",[490,1234,561],{"class":496},[490,1236,627],{"class":538},[490,1238,567],{"class":496},[490,1240,570],{"class":496},[490,1242,634],{"class":573},[490,1244,570],{"class":496},[490,1246,579],{"class":496},[490,1248,518],{"class":496},[490,1250,643],{"class":573},[490,1252,570],{"class":496},[490,1254,579],{"class":496},[490,1256,1257],{"class":650}," 11",[490,1259,603],{"class":496},[490,1261,1262,1264,1266,1269,1271,1274,1276,1279,1281,1283],{"class":492,"line":504},[490,1263,1232],{"class":551},[490,1265,561],{"class":496},[490,1267,1268],{"class":538},"SetFillColor",[490,1270,567],{"class":496},[490,1272,1273],{"class":650},"220",[490,1275,579],{"class":496},[490,1277,1278],{"class":650}," 220",[490,1280,579],{"class":496},[490,1282,1278],{"class":650},[490,1284,603],{"class":496},[490,1286,1287,1289,1291,1294,1296,1299,1301,1304,1306,1308,1311,1313,1315,1318,1321,1323,1325,1328,1330,1332,1335,1337,1339,1343,1345,1347,1349,1351],{"class":492,"line":511},[490,1288,1232],{"class":551},[490,1290,561],{"class":496},[490,1292,1293],{"class":538},"CellFormat",[490,1295,567],{"class":496},[490,1297,1298],{"class":650},"80",[490,1300,579],{"class":496},[490,1302,1303],{"class":650}," 8",[490,1305,579],{"class":496},[490,1307,518],{"class":496},[490,1309,1310],{"class":573},"品名",[490,1312,570],{"class":496},[490,1314,579],{"class":496},[490,1316,1317],{"class":496},"   \"",[490,1319,1320],{"class":573},"1",[490,1322,570],{"class":496},[490,1324,579],{"class":496},[490,1326,1327],{"class":650}," 0",[490,1329,579],{"class":496},[490,1331,518],{"class":496},[490,1333,1334],{"class":573},"L",[490,1336,570],{"class":496},[490,1338,579],{"class":496},[490,1340,1342],{"class":1341},"sfNiH"," true",[490,1344,579],{"class":496},[490,1346,1327],{"class":650},[490,1348,579],{"class":496},[490,1350,600],{"class":496},[490,1352,603],{"class":496},[490,1354,1355,1357,1359,1361,1363,1365,1367,1369,1371,1373,1376,1378,1380,1382,1384,1386,1388,1390,1392,1394,1397,1399,1401,1403,1405,1407,1409,1411],{"class":492,"line":527},[490,1356,1232],{"class":551},[490,1358,561],{"class":496},[490,1360,1293],{"class":538},[490,1362,567],{"class":496},[490,1364,882],{"class":650},[490,1366,579],{"class":496},[490,1368,1303],{"class":650},[490,1370,579],{"class":496},[490,1372,518],{"class":496},[490,1374,1375],{"class":573},"数量",[490,1377,570],{"class":496},[490,1379,579],{"class":496},[490,1381,1317],{"class":496},[490,1383,1320],{"class":573},[490,1385,570],{"class":496},[490,1387,579],{"class":496},[490,1389,1327],{"class":650},[490,1391,579],{"class":496},[490,1393,518],{"class":496},[490,1395,1396],{"class":573},"C",[490,1398,570],{"class":496},[490,1400,579],{"class":496},[490,1402,1342],{"class":1341},[490,1404,579],{"class":496},[490,1406,1327],{"class":650},[490,1408,579],{"class":496},[490,1410,600],{"class":496},[490,1412,603],{"class":496},[490,1414,1415,1417,1419,1421,1423,1426,1428,1430,1432,1434,1437,1439,1441,1443,1445,1447,1449,1451,1453,1455,1458,1460,1462,1464,1466,1468,1470,1472],{"class":492,"line":532},[490,1416,1232],{"class":551},[490,1418,561],{"class":496},[490,1420,1293],{"class":538},[490,1422,567],{"class":496},[490,1424,1425],{"class":650},"30",[490,1427,579],{"class":496},[490,1429,1303],{"class":650},[490,1431,579],{"class":496},[490,1433,518],{"class":496},[490,1435,1436],{"class":573},"单价",[490,1438,570],{"class":496},[490,1440,579],{"class":496},[490,1442,1317],{"class":496},[490,1444,1320],{"class":573},[490,1446,570],{"class":496},[490,1448,579],{"class":496},[490,1450,1327],{"class":650},[490,1452,579],{"class":496},[490,1454,518],{"class":496},[490,1456,1457],{"class":573},"R",[490,1459,570],{"class":496},[490,1461,579],{"class":496},[490,1463,1342],{"class":1341},[490,1465,579],{"class":496},[490,1467,1327],{"class":650},[490,1469,579],{"class":496},[490,1471,600],{"class":496},[490,1473,603],{"class":496},[490,1475,1476,1478,1480,1482,1484,1486,1488,1490,1492,1494,1497,1499,1501,1503,1505,1507,1509,1512,1514,1516,1518,1520,1522,1524,1526,1528,1530,1532],{"class":492,"line":548},[490,1477,1232],{"class":551},[490,1479,561],{"class":496},[490,1481,1293],{"class":538},[490,1483,567],{"class":496},[490,1485,1425],{"class":650},[490,1487,579],{"class":496},[490,1489,1303],{"class":650},[490,1491,579],{"class":496},[490,1493,518],{"class":496},[490,1495,1496],{"class":573},"金额",[490,1498,570],{"class":496},[490,1500,579],{"class":496},[490,1502,1317],{"class":496},[490,1504,1320],{"class":573},[490,1506,570],{"class":496},[490,1508,579],{"class":496},[490,1510,1511],{"class":650}," 1",[490,1513,579],{"class":496},[490,1515,518],{"class":496},[490,1517,1457],{"class":573},[490,1519,570],{"class":496},[490,1521,579],{"class":496},[490,1523,1342],{"class":1341},[490,1525,579],{"class":496},[490,1527,1327],{"class":650},[490,1529,579],{"class":496},[490,1531,600],{"class":496},[490,1533,603],{"class":496},[490,1535,1536],{"class":492,"line":606},[490,1537,508],{"emptyLinePlaceholder":507},[490,1539,1540,1542,1544,1546,1548,1550,1552,1554,1556,1558,1560,1562],{"class":492,"line":620},[490,1541,1232],{"class":551},[490,1543,561],{"class":496},[490,1545,627],{"class":538},[490,1547,567],{"class":496},[490,1549,570],{"class":496},[490,1551,634],{"class":573},[490,1553,570],{"class":496},[490,1555,579],{"class":496},[490,1557,600],{"class":496},[490,1559,579],{"class":496},[490,1561,1257],{"class":650},[490,1563,603],{"class":496},[490,1565,1566,1569,1571,1574,1578],{"class":492,"line":656},[490,1567,1568],{"class":551},"items ",[490,1570,555],{"class":496},[490,1572,1573],{"class":496}," [][]",[490,1575,1577],{"class":1576},"spNyl","string",[490,1579,1580],{"class":496},"{\n",[490,1582,1583,1586,1588,1591,1593,1595,1597,1600,1602,1604,1606,1609,1611,1613,1615,1618,1620],{"class":492,"line":687},[490,1584,1585],{"class":496},"    {",[490,1587,570],{"class":496},[490,1589,1590],{"class":573},"前端开发",[490,1592,570],{"class":496},[490,1594,579],{"class":496},[490,1596,518],{"class":496},[490,1598,1599],{"class":573},"40h",[490,1601,570],{"class":496},[490,1603,579],{"class":496},[490,1605,518],{"class":496},[490,1607,1608],{"class":573},"¥1,500",[490,1610,570],{"class":496},[490,1612,579],{"class":496},[490,1614,518],{"class":496},[490,1616,1617],{"class":573},"¥60,000",[490,1619,570],{"class":496},[490,1621,1622],{"class":496},"},\n",[490,1624,1625,1627,1629,1632,1634,1636,1638,1641,1643,1645,1647,1649,1651,1653,1655,1658,1660],{"class":492,"line":708},[490,1626,1585],{"class":496},[490,1628,570],{"class":496},[490,1630,1631],{"class":573},"后端开发",[490,1633,570],{"class":496},[490,1635,579],{"class":496},[490,1637,518],{"class":496},[490,1639,1640],{"class":573},"60h",[490,1642,570],{"class":496},[490,1644,579],{"class":496},[490,1646,518],{"class":496},[490,1648,1608],{"class":573},[490,1650,570],{"class":496},[490,1652,579],{"class":496},[490,1654,518],{"class":496},[490,1656,1657],{"class":573},"¥90,000",[490,1659,570],{"class":496},[490,1661,1622],{"class":496},[490,1663,1664,1666,1668,1671,1673,1675,1677,1680,1682,1684,1686,1689,1691,1693,1695,1698,1700],{"class":492,"line":799},[490,1665,1585],{"class":496},[490,1667,570],{"class":496},[490,1669,1670],{"class":573},"UI 设计",[490,1672,570],{"class":496},[490,1674,579],{"class":496},[490,1676,518],{"class":496},[490,1678,1679],{"class":573},"20h",[490,1681,570],{"class":496},[490,1683,579],{"class":496},[490,1685,518],{"class":496},[490,1687,1688],{"class":573},"¥1,200",[490,1690,570],{"class":496},[490,1692,579],{"class":496},[490,1694,518],{"class":496},[490,1696,1697],{"class":573},"¥24,000",[490,1699,570],{"class":496},[490,1701,1622],{"class":496},[490,1703,1704],{"class":492,"line":810},[490,1705,711],{"class":496},[490,1707,1708,1711,1714,1716,1719,1721,1724,1727],{"class":492,"line":829},[490,1709,1710],{"class":514},"for",[490,1712,1713],{"class":551}," _",[490,1715,579],{"class":496},[490,1717,1718],{"class":551}," row ",[490,1720,555],{"class":496},[490,1722,1723],{"class":514}," range",[490,1725,1726],{"class":551}," items ",[490,1728,1580],{"class":496},[490,1730,1731,1733,1735,1737,1739,1741,1743,1745,1747,1750,1753,1756,1759,1761,1763,1765,1767,1769,1771,1773,1775,1777,1779,1782,1784,1786,1788,1790],{"class":492,"line":852},[490,1732,609],{"class":551},[490,1734,561],{"class":496},[490,1736,1293],{"class":538},[490,1738,567],{"class":496},[490,1740,1298],{"class":650},[490,1742,579],{"class":496},[490,1744,1303],{"class":650},[490,1746,579],{"class":496},[490,1748,1749],{"class":551}," row",[490,1751,1752],{"class":496},"[",[490,1754,1755],{"class":650},"0",[490,1757,1758],{"class":496},"],",[490,1760,518],{"class":496},[490,1762,1320],{"class":573},[490,1764,570],{"class":496},[490,1766,579],{"class":496},[490,1768,1327],{"class":650},[490,1770,579],{"class":496},[490,1772,518],{"class":496},[490,1774,1334],{"class":573},[490,1776,570],{"class":496},[490,1778,579],{"class":496},[490,1780,1781],{"class":1341}," false",[490,1783,579],{"class":496},[490,1785,1327],{"class":650},[490,1787,579],{"class":496},[490,1789,600],{"class":496},[490,1791,603],{"class":496},[490,1793,1794,1796,1798,1800,1802,1804,1806,1808,1810,1812,1814,1816,1818,1820,1822,1824,1826,1828,1830,1832,1834,1836,1838,1840,1842,1844,1846,1848],{"class":492,"line":888},[490,1795,609],{"class":551},[490,1797,561],{"class":496},[490,1799,1293],{"class":538},[490,1801,567],{"class":496},[490,1803,882],{"class":650},[490,1805,579],{"class":496},[490,1807,1303],{"class":650},[490,1809,579],{"class":496},[490,1811,1749],{"class":551},[490,1813,1752],{"class":496},[490,1815,1320],{"class":650},[490,1817,1758],{"class":496},[490,1819,518],{"class":496},[490,1821,1320],{"class":573},[490,1823,570],{"class":496},[490,1825,579],{"class":496},[490,1827,1327],{"class":650},[490,1829,579],{"class":496},[490,1831,518],{"class":496},[490,1833,1396],{"class":573},[490,1835,570],{"class":496},[490,1837,579],{"class":496},[490,1839,1781],{"class":1341},[490,1841,579],{"class":496},[490,1843,1327],{"class":650},[490,1845,579],{"class":496},[490,1847,600],{"class":496},[490,1849,603],{"class":496},[490,1851,1852,1854,1856,1858,1860,1862,1864,1866,1868,1870,1872,1875,1877,1879,1881,1883,1885,1887,1889,1891,1893,1895,1897,1899,1901,1903,1905,1907],{"class":492,"line":894},[490,1853,609],{"class":551},[490,1855,561],{"class":496},[490,1857,1293],{"class":538},[490,1859,567],{"class":496},[490,1861,1425],{"class":650},[490,1863,579],{"class":496},[490,1865,1303],{"class":650},[490,1867,579],{"class":496},[490,1869,1749],{"class":551},[490,1871,1752],{"class":496},[490,1873,1874],{"class":650},"2",[490,1876,1758],{"class":496},[490,1878,518],{"class":496},[490,1880,1320],{"class":573},[490,1882,570],{"class":496},[490,1884,579],{"class":496},[490,1886,1327],{"class":650},[490,1888,579],{"class":496},[490,1890,518],{"class":496},[490,1892,1457],{"class":573},[490,1894,570],{"class":496},[490,1896,579],{"class":496},[490,1898,1781],{"class":1341},[490,1900,579],{"class":496},[490,1902,1327],{"class":650},[490,1904,579],{"class":496},[490,1906,600],{"class":496},[490,1908,603],{"class":496},[490,1910,1911,1913,1915,1917,1919,1921,1923,1925,1927,1929,1931,1934,1936,1938,1940,1942,1944,1946,1948,1950,1952,1954,1956,1958,1960,1962,1964,1966],{"class":492,"line":899},[490,1912,609],{"class":551},[490,1914,561],{"class":496},[490,1916,1293],{"class":538},[490,1918,567],{"class":496},[490,1920,1425],{"class":650},[490,1922,579],{"class":496},[490,1924,1303],{"class":650},[490,1926,579],{"class":496},[490,1928,1749],{"class":551},[490,1930,1752],{"class":496},[490,1932,1933],{"class":650},"3",[490,1935,1758],{"class":496},[490,1937,518],{"class":496},[490,1939,1320],{"class":573},[490,1941,570],{"class":496},[490,1943,579],{"class":496},[490,1945,1511],{"class":650},[490,1947,579],{"class":496},[490,1949,518],{"class":496},[490,1951,1457],{"class":573},[490,1953,570],{"class":496},[490,1955,579],{"class":496},[490,1957,1781],{"class":1341},[490,1959,579],{"class":496},[490,1961,1327],{"class":650},[490,1963,579],{"class":496},[490,1965,600],{"class":496},[490,1967,603],{"class":496},[490,1969,1970],{"class":492,"line":916},[490,1971,711],{"class":496},[18,1973,1974],{},"列宽自己心算，品名换行则崩。",[18,1976,1977],{},[21,1978,716],{},[481,1980,1982],{"className":483,"code":1981,"language":485,"meta":486,"style":486},"page.AutoRow(func(r *template.RowBuilder) {\n    r.Col(12, func(c *template.ColBuilder) {\n        c.Table(\n            []string{\"品名\", \"数量\", \"单价\", \"金额\"},\n            [][]string{\n                {\"前端开发\", \"40h\", \"¥1,500\", \"¥60,000\"},\n                {\"后端开发\", \"60h\", \"¥1,500\", \"¥90,000\"},\n                {\"UI 设计\", \"20h\", \"¥1,200\", \"¥24,000\"},\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            template.TableStripe(pdf.RGBHex(0xF5F5F5)),\n        )\n    })\n})\n",[26,1983,1984,2009,2040,2052,2094,2103,2140,2176,2212,2217,2248,2259,2271,2291,2317,2322,2346,2351,2355],{"__ignoreMap":486},[490,1985,1986,1989,1991,1993,1995,1997,1999,2001,2003,2005,2007],{"class":492,"line":493},[490,1987,1988],{"class":551},"page",[490,1990,561],{"class":496},[490,1992,924],{"class":538},[490,1994,927],{"class":496},[490,1996,931],{"class":930},[490,1998,934],{"class":496},[490,2000,937],{"class":500},[490,2002,561],{"class":496},[490,2004,942],{"class":500},[490,2006,207],{"class":496},[490,2008,545],{"class":496},[490,2010,2011,2014,2016,2018,2020,2022,2024,2026,2028,2030,2032,2034,2036,2038],{"class":492,"line":504},[490,2012,2013],{"class":551},"    r",[490,2015,561],{"class":496},[490,2017,957],{"class":538},[490,2019,567],{"class":496},[490,2021,962],{"class":650},[490,2023,579],{"class":496},[490,2025,967],{"class":496},[490,2027,970],{"class":930},[490,2029,934],{"class":496},[490,2031,937],{"class":500},[490,2033,561],{"class":496},[490,2035,979],{"class":500},[490,2037,207],{"class":496},[490,2039,545],{"class":496},[490,2041,2042,2045,2047,2050],{"class":492,"line":511},[490,2043,2044],{"class":551},"        c",[490,2046,561],{"class":496},[490,2048,2049],{"class":538},"Table",[490,2051,826],{"class":496},[490,2053,2054,2057,2059,2062,2064,2066,2068,2070,2072,2074,2076,2078,2080,2082,2084,2086,2088,2090,2092],{"class":492,"line":527},[490,2055,2056],{"class":496},"            []",[490,2058,1577],{"class":1576},[490,2060,2061],{"class":496},"{",[490,2063,570],{"class":496},[490,2065,1310],{"class":573},[490,2067,570],{"class":496},[490,2069,579],{"class":496},[490,2071,518],{"class":496},[490,2073,1375],{"class":573},[490,2075,570],{"class":496},[490,2077,579],{"class":496},[490,2079,518],{"class":496},[490,2081,1436],{"class":573},[490,2083,570],{"class":496},[490,2085,579],{"class":496},[490,2087,518],{"class":496},[490,2089,1496],{"class":573},[490,2091,570],{"class":496},[490,2093,1622],{"class":496},[490,2095,2096,2099,2101],{"class":492,"line":532},[490,2097,2098],{"class":496},"            [][]",[490,2100,1577],{"class":1576},[490,2102,1580],{"class":496},[490,2104,2105,2108,2110,2112,2114,2116,2118,2120,2122,2124,2126,2128,2130,2132,2134,2136,2138],{"class":492,"line":548},[490,2106,2107],{"class":496},"                {",[490,2109,570],{"class":496},[490,2111,1590],{"class":573},[490,2113,570],{"class":496},[490,2115,579],{"class":496},[490,2117,518],{"class":496},[490,2119,1599],{"class":573},[490,2121,570],{"class":496},[490,2123,579],{"class":496},[490,2125,518],{"class":496},[490,2127,1608],{"class":573},[490,2129,570],{"class":496},[490,2131,579],{"class":496},[490,2133,518],{"class":496},[490,2135,1617],{"class":573},[490,2137,570],{"class":496},[490,2139,1622],{"class":496},[490,2141,2142,2144,2146,2148,2150,2152,2154,2156,2158,2160,2162,2164,2166,2168,2170,2172,2174],{"class":492,"line":606},[490,2143,2107],{"class":496},[490,2145,570],{"class":496},[490,2147,1631],{"class":573},[490,2149,570],{"class":496},[490,2151,579],{"class":496},[490,2153,518],{"class":496},[490,2155,1640],{"class":573},[490,2157,570],{"class":496},[490,2159,579],{"class":496},[490,2161,518],{"class":496},[490,2163,1608],{"class":573},[490,2165,570],{"class":496},[490,2167,579],{"class":496},[490,2169,518],{"class":496},[490,2171,1657],{"class":573},[490,2173,570],{"class":496},[490,2175,1622],{"class":496},[490,2177,2178,2180,2182,2184,2186,2188,2190,2192,2194,2196,2198,2200,2202,2204,2206,2208,2210],{"class":492,"line":620},[490,2179,2107],{"class":496},[490,2181,570],{"class":496},[490,2183,1670],{"class":573},[490,2185,570],{"class":496},[490,2187,579],{"class":496},[490,2189,518],{"class":496},[490,2191,1679],{"class":573},[490,2193,570],{"class":496},[490,2195,579],{"class":496},[490,2197,518],{"class":496},[490,2199,1688],{"class":573},[490,2201,570],{"class":496},[490,2203,579],{"class":496},[490,2205,518],{"class":496},[490,2207,1697],{"class":573},[490,2209,570],{"class":496},[490,2211,1622],{"class":496},[490,2213,2214],{"class":492,"line":656},[490,2215,2216],{"class":496},"            },\n",[490,2218,2219,2222,2224,2227,2229,2232,2234,2237,2239,2241,2243,2246],{"class":492,"line":687},[490,2220,2221],{"class":551},"            template",[490,2223,561],{"class":496},[490,2225,2226],{"class":538},"ColumnWidths",[490,2228,567],{"class":496},[490,2230,2231],{"class":650},"50",[490,2233,579],{"class":496},[490,2235,2236],{"class":650}," 15",[490,2238,579],{"class":496},[490,2240,2236],{"class":650},[490,2242,579],{"class":496},[490,2244,2245],{"class":650}," 20",[490,2247,849],{"class":496},[490,2249,2250,2252,2254,2257],{"class":492,"line":708},[490,2251,2221],{"class":551},[490,2253,561],{"class":496},[490,2255,2256],{"class":538},"TableHeaderStyle",[490,2258,826],{"class":496},[490,2260,2261,2264,2266,2268],{"class":492,"line":799},[490,2262,2263],{"class":551},"                template",[490,2265,561],{"class":496},[490,2267,1027],{"class":538},[490,2269,2270],{"class":496},"(),\n",[490,2272,2273,2275,2277,2280,2282,2284,2286,2289],{"class":492,"line":810},[490,2274,2263],{"class":551},[490,2276,561],{"class":496},[490,2278,2279],{"class":538},"TextColor",[490,2281,567],{"class":496},[490,2283,1232],{"class":551},[490,2285,561],{"class":496},[490,2287,2288],{"class":551},"White",[490,2290,849],{"class":496},[490,2292,2293,2295,2297,2300,2302,2304,2306,2309,2311,2314],{"class":492,"line":829},[490,2294,2263],{"class":551},[490,2296,561],{"class":496},[490,2298,2299],{"class":538},"BgColor",[490,2301,567],{"class":496},[490,2303,1232],{"class":551},[490,2305,561],{"class":496},[490,2307,2308],{"class":538},"RGBHex",[490,2310,567],{"class":496},[490,2312,2313],{"class":650},"0x1A237E",[490,2315,2316],{"class":496},")),\n",[490,2318,2319],{"class":492,"line":852},[490,2320,2321],{"class":496},"            ),\n",[490,2323,2324,2326,2328,2331,2333,2335,2337,2339,2341,2344],{"class":492,"line":888},[490,2325,2221],{"class":551},[490,2327,561],{"class":496},[490,2329,2330],{"class":538},"TableStripe",[490,2332,567],{"class":496},[490,2334,1232],{"class":551},[490,2336,561],{"class":496},[490,2338,2308],{"class":538},[490,2340,567],{"class":496},[490,2342,2343],{"class":650},"0xF5F5F5",[490,2345,2316],{"class":496},[490,2347,2348],{"class":492,"line":894},[490,2349,2350],{"class":496},"        )\n",[490,2352,2353],{"class":492,"line":899},[490,2354,1042],{"class":496},[490,2356,2357],{"class":492,"line":916},[490,2358,2359],{"class":496},"})\n",[18,2361,2362,2365,2366,2369,2370,2373,2374,2376],{},[26,2363,2364],{},"ColumnWidths(50, 15, 15, 20)"," 里的数字是",[21,2367,2368],{},"所在列宽的百分比","，不是绝对毫米。把这张表放进 ",[26,2371,2372],{},"r.Col(6, ...)","，同一组百分比依然成立 —— 这是 ",[26,2375,1293],{}," 必须包一层才能达到的抽象。",[18,2378,2379],{},"自动换行。自动分页 —— 表格超出下边距时，下一页自动重绘表头。",[13,2381,2383],{"id":2382},"before-after-3不用再跳那套-cjk-舞步","Before / After 3：不用再跳那套 CJK 舞步",[18,2385,2386,2387,2389],{},"这是我决定弃用 gofpdf 的那一点。在 gofpdf 里要渲染中文，你得调 ",[26,2388,28],{},"，指一个磁盘 TTF 路径，设置字体，然后祈祷。子集化大部分时候能用。有些 TTF 会触发 glyph-id 冲突并吐出乱码。错误信息帮不上忙。",[18,2391,2392],{},[21,2393,479],{},[481,2395,2397],{"className":483,"code":2396,"language":485,"meta":486,"style":486},"pdf := gofpdf.New(\"P\", \"mm\", \"A4\", \"\")\npdf.AddUTF8Font(\"notosanssc\", \"\", \"NotoSansSC-Regular.ttf\")\npdf.AddPage()\npdf.SetFont(\"notosanssc\", \"\", 14)\npdf.Cell(0, 10, \"你好，世界。\")\npdf.OutputFileAndClose(\"zh.pdf\")\n",[26,2398,2399,2442,2474,2484,2511,2538],{"__ignoreMap":486},[490,2400,2401,2404,2406,2408,2410,2412,2414,2416,2418,2420,2422,2424,2426,2428,2430,2432,2434,2436,2438,2440],{"class":492,"line":493},[490,2402,2403],{"class":551},"pdf ",[490,2405,555],{"class":496},[490,2407,558],{"class":551},[490,2409,561],{"class":496},[490,2411,564],{"class":538},[490,2413,567],{"class":496},[490,2415,570],{"class":496},[490,2417,574],{"class":573},[490,2419,570],{"class":496},[490,2421,579],{"class":496},[490,2423,518],{"class":496},[490,2425,584],{"class":573},[490,2427,570],{"class":496},[490,2429,579],{"class":496},[490,2431,518],{"class":496},[490,2433,593],{"class":573},[490,2435,570],{"class":496},[490,2437,579],{"class":496},[490,2439,600],{"class":496},[490,2441,603],{"class":496},[490,2443,2444,2446,2448,2450,2452,2454,2457,2459,2461,2463,2465,2467,2470,2472],{"class":492,"line":504},[490,2445,1232],{"class":551},[490,2447,561],{"class":496},[490,2449,28],{"class":538},[490,2451,567],{"class":496},[490,2453,570],{"class":496},[490,2455,2456],{"class":573},"notosanssc",[490,2458,570],{"class":496},[490,2460,579],{"class":496},[490,2462,600],{"class":496},[490,2464,579],{"class":496},[490,2466,518],{"class":496},[490,2468,2469],{"class":573},"NotoSansSC-Regular.ttf",[490,2471,570],{"class":496},[490,2473,603],{"class":496},[490,2475,2476,2478,2480,2482],{"class":492,"line":511},[490,2477,1232],{"class":551},[490,2479,561],{"class":496},[490,2481,614],{"class":538},[490,2483,617],{"class":496},[490,2485,2486,2488,2490,2492,2494,2496,2498,2500,2502,2504,2506,2509],{"class":492,"line":527},[490,2487,1232],{"class":551},[490,2489,561],{"class":496},[490,2491,627],{"class":538},[490,2493,567],{"class":496},[490,2495,570],{"class":496},[490,2497,2456],{"class":573},[490,2499,570],{"class":496},[490,2501,579],{"class":496},[490,2503,600],{"class":496},[490,2505,579],{"class":496},[490,2507,2508],{"class":650}," 14",[490,2510,603],{"class":496},[490,2512,2513,2515,2517,2519,2521,2523,2525,2527,2529,2531,2534,2536],{"class":492,"line":532},[490,2514,1232],{"class":551},[490,2516,561],{"class":496},[490,2518,663],{"class":538},[490,2520,567],{"class":496},[490,2522,1755],{"class":650},[490,2524,579],{"class":496},[490,2526,673],{"class":650},[490,2528,579],{"class":496},[490,2530,518],{"class":496},[490,2532,2533],{"class":573},"你好，世界。",[490,2535,570],{"class":496},[490,2537,603],{"class":496},[490,2539,2540,2542,2544,2546,2548,2550,2553,2555],{"class":492,"line":548},[490,2541,1232],{"class":551},[490,2543,561],{"class":496},[490,2545,694],{"class":538},[490,2547,567],{"class":496},[490,2549,570],{"class":496},[490,2551,2552],{"class":573},"zh.pdf",[490,2554,570],{"class":496},[490,2556,603],{"class":496},[18,2558,2559,2560,2563,2564,2566,2567,2569],{},"两颗地雷：TTF 必须在",[21,2561,2562],{},"运行时","以指定路径存在于运行二进制的机器上（所以你的 Docker 镜像得捆一份字体）；",[26,2565,663],{}," 宽度给 ",[26,2568,1755],{}," 意思是\"到右边距\"，但中文里宽度估算常算不准全角字符，容易超框被截断。",[18,2571,2572],{},[21,2573,716],{},[481,2575,2577],{"className":483,"code":2576,"language":485,"meta":486,"style":486},"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/template\"\n)\n\nfunc main() {\n    fontData, err := os.ReadFile(\"NotoSansSC-Regular.ttf\")\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    doc := gpdf.NewDocument(\n        gpdf.WithPageSize(document.A4),\n        gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n        gpdf.WithFont(\"NotoSansSC\", fontData),\n        gpdf.WithDefaultFont(\"NotoSansSC\", 14),\n    )\n\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"你好，世界。\")\n            c.Text(\"天行健，君子以自强不息。\")\n            c.Text(\"北京市朝阳区建国门外大街 1 号\")\n        })\n    })\n\n    data, _ := doc.Generate()\n    os.WriteFile(\"zh.pdf\", data, 0o644)\n}\n",[26,2578,2579,2585,2589,2595,2603,2611,2615,2623,2631,2639,2643,2647,2657,2685,2697,2711,2715,2719,2733,2751,2781,2806,2829,2833,2837,2851,2875,2905,2923,2942,2961,2965,2969,2974,2994,3022],{"__ignoreMap":486},[490,2580,2581,2583],{"class":492,"line":493},[490,2582,497],{"class":496},[490,2584,501],{"class":500},[490,2586,2587],{"class":492,"line":504},[490,2588,508],{"emptyLinePlaceholder":507},[490,2590,2591,2593],{"class":492,"line":511},[490,2592,515],{"class":514},[490,2594,738],{"class":496},[490,2596,2597,2599,2601],{"class":492,"line":527},[490,2598,743],{"class":496},[490,2600,746],{"class":500},[490,2602,524],{"class":496},[490,2604,2605,2607,2609],{"class":492,"line":532},[490,2606,743],{"class":496},[490,2608,755],{"class":500},[490,2610,524],{"class":496},[490,2612,2613],{"class":492,"line":548},[490,2614,508],{"emptyLinePlaceholder":507},[490,2616,2617,2619,2621],{"class":492,"line":606},[490,2618,743],{"class":496},[490,2620,768],{"class":500},[490,2622,524],{"class":496},[490,2624,2625,2627,2629],{"class":492,"line":620},[490,2626,743],{"class":496},[490,2628,777],{"class":500},[490,2630,524],{"class":496},[490,2632,2633,2635,2637],{"class":492,"line":656},[490,2634,743],{"class":496},[490,2636,786],{"class":500},[490,2638,524],{"class":496},[490,2640,2641],{"class":492,"line":687},[490,2642,603],{"class":496},[490,2644,2645],{"class":492,"line":708},[490,2646,508],{"emptyLinePlaceholder":507},[490,2648,2649,2651,2653,2655],{"class":492,"line":799},[490,2650,535],{"class":496},[490,2652,539],{"class":538},[490,2654,542],{"class":496},[490,2656,545],{"class":496},[490,2658,2659,2662,2664,2666,2668,2670,2672,2675,2677,2679,2681,2683],{"class":492,"line":810},[490,2660,2661],{"class":551},"    fontData",[490,2663,579],{"class":496},[490,2665,1058],{"class":551},[490,2667,555],{"class":496},[490,2669,1121],{"class":551},[490,2671,561],{"class":496},[490,2673,2674],{"class":538},"ReadFile",[490,2676,567],{"class":496},[490,2678,570],{"class":496},[490,2680,2469],{"class":573},[490,2682,570],{"class":496},[490,2684,603],{"class":496},[490,2686,2687,2689,2691,2693,2695],{"class":492,"line":829},[490,2688,1075],{"class":514},[490,2690,1058],{"class":551},[490,2692,1080],{"class":496},[490,2694,1083],{"class":496},[490,2696,545],{"class":496},[490,2698,2699,2701,2703,2705,2707,2709],{"class":492,"line":852},[490,2700,1091],{"class":551},[490,2702,561],{"class":496},[490,2704,1096],{"class":538},[490,2706,567],{"class":496},[490,2708,1101],{"class":551},[490,2710,603],{"class":496},[490,2712,2713],{"class":492,"line":888},[490,2714,1109],{"class":496},[490,2716,2717],{"class":492,"line":894},[490,2718,508],{"emptyLinePlaceholder":507},[490,2720,2721,2723,2725,2727,2729,2731],{"class":492,"line":899},[490,2722,813],{"class":551},[490,2724,555],{"class":496},[490,2726,818],{"class":551},[490,2728,561],{"class":496},[490,2730,823],{"class":538},[490,2732,826],{"class":496},[490,2734,2735,2737,2739,2741,2743,2745,2747,2749],{"class":492,"line":916},[490,2736,832],{"class":551},[490,2738,561],{"class":496},[490,2740,837],{"class":538},[490,2742,567],{"class":496},[490,2744,842],{"class":551},[490,2746,561],{"class":496},[490,2748,593],{"class":551},[490,2750,849],{"class":496},[490,2752,2753,2755,2757,2759,2761,2763,2765,2767,2769,2771,2773,2775,2777,2779],{"class":492,"line":949},[490,2754,832],{"class":551},[490,2756,561],{"class":496},[490,2758,859],{"class":538},[490,2760,567],{"class":496},[490,2762,842],{"class":551},[490,2764,561],{"class":496},[490,2766,868],{"class":538},[490,2768,567],{"class":496},[490,2770,842],{"class":551},[490,2772,561],{"class":496},[490,2774,877],{"class":538},[490,2776,567],{"class":496},[490,2778,882],{"class":650},[490,2780,885],{"class":496},[490,2782,2783,2785,2787,2790,2792,2794,2797,2799,2801,2804],{"class":492,"line":986},[490,2784,832],{"class":551},[490,2786,561],{"class":496},[490,2788,2789],{"class":538},"WithFont",[490,2791,567],{"class":496},[490,2793,570],{"class":496},[490,2795,2796],{"class":573},"NotoSansSC",[490,2798,570],{"class":496},[490,2800,579],{"class":496},[490,2802,2803],{"class":551}," fontData",[490,2805,849],{"class":496},[490,2807,2808,2810,2812,2815,2817,2819,2821,2823,2825,2827],{"class":492,"line":1033},[490,2809,832],{"class":551},[490,2811,561],{"class":496},[490,2813,2814],{"class":538},"WithDefaultFont",[490,2816,567],{"class":496},[490,2818,570],{"class":496},[490,2820,2796],{"class":573},[490,2822,570],{"class":496},[490,2824,579],{"class":496},[490,2826,2508],{"class":650},[490,2828,849],{"class":496},[490,2830,2831],{"class":492,"line":1039},[490,2832,891],{"class":496},[490,2834,2835],{"class":492,"line":1045},[490,2836,508],{"emptyLinePlaceholder":507},[490,2838,2839,2841,2843,2845,2847,2849],{"class":492,"line":1050},[490,2840,902],{"class":551},[490,2842,555],{"class":496},[490,2844,907],{"class":551},[490,2846,561],{"class":496},[490,2848,614],{"class":538},[490,2850,617],{"class":496},[490,2852,2853,2855,2857,2859,2861,2863,2865,2867,2869,2871,2873],{"class":492,"line":1072},[490,2854,919],{"class":551},[490,2856,561],{"class":496},[490,2858,924],{"class":538},[490,2860,927],{"class":496},[490,2862,931],{"class":930},[490,2864,934],{"class":496},[490,2866,937],{"class":500},[490,2868,561],{"class":496},[490,2870,942],{"class":500},[490,2872,207],{"class":496},[490,2874,545],{"class":496},[490,2876,2877,2879,2881,2883,2885,2887,2889,2891,2893,2895,2897,2899,2901,2903],{"class":492,"line":1088},[490,2878,952],{"class":551},[490,2880,561],{"class":496},[490,2882,957],{"class":538},[490,2884,567],{"class":496},[490,2886,962],{"class":650},[490,2888,579],{"class":496},[490,2890,967],{"class":496},[490,2892,970],{"class":930},[490,2894,934],{"class":496},[490,2896,937],{"class":500},[490,2898,561],{"class":496},[490,2900,979],{"class":500},[490,2902,207],{"class":496},[490,2904,545],{"class":496},[490,2906,2907,2909,2911,2913,2915,2917,2919,2921],{"class":492,"line":1106},[490,2908,989],{"class":551},[490,2910,561],{"class":496},[490,2912,994],{"class":538},[490,2914,567],{"class":496},[490,2916,570],{"class":496},[490,2918,2533],{"class":573},[490,2920,570],{"class":496},[490,2922,603],{"class":496},[490,2924,2925,2927,2929,2931,2933,2935,2938,2940],{"class":492,"line":1112},[490,2926,989],{"class":551},[490,2928,561],{"class":496},[490,2930,994],{"class":538},[490,2932,567],{"class":496},[490,2934,570],{"class":496},[490,2936,2937],{"class":573},"天行健，君子以自强不息。",[490,2939,570],{"class":496},[490,2941,603],{"class":496},[490,2943,2944,2946,2948,2950,2952,2954,2957,2959],{"class":492,"line":1158},[490,2945,989],{"class":551},[490,2947,561],{"class":496},[490,2949,994],{"class":538},[490,2951,567],{"class":496},[490,2953,570],{"class":496},[490,2955,2956],{"class":573},"北京市朝阳区建国门外大街 1 号",[490,2958,570],{"class":496},[490,2960,603],{"class":496},[490,2962,2963],{"class":492,"line":1173},[490,2964,1036],{"class":496},[490,2966,2967],{"class":492,"line":1178},[490,2968,1042],{"class":496},[490,2970,2972],{"class":492,"line":2971},33,[490,2973,508],{"emptyLinePlaceholder":507},[490,2975,2977,2979,2981,2984,2986,2988,2990,2992],{"class":492,"line":2976},34,[490,2978,1053],{"class":551},[490,2980,579],{"class":496},[490,2982,2983],{"class":551}," _ ",[490,2985,555],{"class":496},[490,2987,907],{"class":551},[490,2989,561],{"class":496},[490,2991,1067],{"class":538},[490,2993,617],{"class":496},[490,2995,2997,3000,3002,3004,3006,3008,3010,3012,3014,3016,3018,3020],{"class":492,"line":2996},35,[490,2998,2999],{"class":551},"    os",[490,3001,561],{"class":496},[490,3003,1126],{"class":538},[490,3005,567],{"class":496},[490,3007,570],{"class":496},[490,3009,2552],{"class":573},[490,3011,570],{"class":496},[490,3013,579],{"class":496},[490,3015,1139],{"class":551},[490,3017,579],{"class":496},[490,3019,1144],{"class":650},[490,3021,603],{"class":496},[490,3023,3025],{"class":492,"line":3024},36,[490,3026,711],{"class":496},[18,3028,3029],{},"两处不同。",[18,3031,3032,3033,3036,3037,3040],{},"其一：",[21,3034,3035],{},"传字节切片，不传路径","。用 ",[26,3038,3039],{},"//go:embed NotoSansSC-Regular.ttf"," 把 TTF 嵌进二进制，部署时就自包含，不会出现\"生产环境找不到字体\"的情况。",[18,3042,3043],{},"其二：gpdf 的 TrueType 子集化器理解 CJK 的 cmap 格式（4、6、12）与 Identity-H 编码。最终 PDF 只包含你实际用到的字形 —— 一份 200 字符的中文发票嵌入 NotoSansSC 后，字体子集约 30 KB，而不是完整 4 MB。如果你见过 gofpdf 生成一页中文就 5 MB 的 PDF，这是你会第一眼察觉的差别。",[18,3045,3046],{},"关于思源黑体、方正系列、字体回退等更深入的 CJK 话题，会在后续文章细讲。",[13,3048,3050],{"id":3049},"before-after-4每页固定页眉-页脚带页码","Before / After 4：每页固定页眉 + 页脚带页码",[18,3052,3053,3054,223,3057,3060,3061,3064,3065,3067,3068,3071],{},"gofpdf 处理重复框架用 ",[26,3055,3056],{},"SetHeaderFunc",[26,3058,3059],{},"SetFooterFunc","，两个都接收一个针对当前光标运行的 ",[26,3062,3063],{},"func()","。页码用 ",[26,3066,386],{}," + ",[26,3069,3070],{},"pdf.AliasNbPages()","。",[18,3073,3074],{},[21,3075,479],{},[481,3077,3079],{"className":483,"code":3078,"language":485,"meta":486,"style":486},"pdf := gofpdf.New(\"P\", \"mm\", \"A4\", \"\")\npdf.SetHeaderFunc(func() {\n    pdf.SetFont(\"Arial\", \"B\", 12)\n    pdf.Cell(0, 10, \"ACME 科技有限公司\")\n    pdf.Ln(15)\n})\npdf.SetFooterFunc(func() {\n    pdf.SetY(-15)\n    pdf.SetFont(\"Arial\", \"I\", 8)\n    pdf.CellFormat(0, 10,\n        fmt.Sprintf(\"Page %d/{nb}\", pdf.PageNo()),\n        \"\", 0, \"C\", false, 0, \"\")\n})\npdf.AliasNbPages(\"\")\npdf.AddPage()\n// ... body ...\n",[26,3080,3081,3123,3136,3167,3194,3210,3214,3226,3242,3273,3292,3331,3362,3366,3382,3392],{"__ignoreMap":486},[490,3082,3083,3085,3087,3089,3091,3093,3095,3097,3099,3101,3103,3105,3107,3109,3111,3113,3115,3117,3119,3121],{"class":492,"line":493},[490,3084,2403],{"class":551},[490,3086,555],{"class":496},[490,3088,558],{"class":551},[490,3090,561],{"class":496},[490,3092,564],{"class":538},[490,3094,567],{"class":496},[490,3096,570],{"class":496},[490,3098,574],{"class":573},[490,3100,570],{"class":496},[490,3102,579],{"class":496},[490,3104,518],{"class":496},[490,3106,584],{"class":573},[490,3108,570],{"class":496},[490,3110,579],{"class":496},[490,3112,518],{"class":496},[490,3114,593],{"class":573},[490,3116,570],{"class":496},[490,3118,579],{"class":496},[490,3120,600],{"class":496},[490,3122,603],{"class":496},[490,3124,3125,3127,3129,3131,3134],{"class":492,"line":504},[490,3126,1232],{"class":551},[490,3128,561],{"class":496},[490,3130,3056],{"class":538},[490,3132,3133],{"class":496},"(func()",[490,3135,545],{"class":496},[490,3137,3138,3140,3142,3144,3146,3148,3150,3152,3154,3156,3158,3160,3162,3165],{"class":492,"line":511},[490,3139,609],{"class":551},[490,3141,561],{"class":496},[490,3143,627],{"class":538},[490,3145,567],{"class":496},[490,3147,570],{"class":496},[490,3149,634],{"class":573},[490,3151,570],{"class":496},[490,3153,579],{"class":496},[490,3155,518],{"class":496},[490,3157,643],{"class":573},[490,3159,570],{"class":496},[490,3161,579],{"class":496},[490,3163,3164],{"class":650}," 12",[490,3166,603],{"class":496},[490,3168,3169,3171,3173,3175,3177,3179,3181,3183,3185,3187,3190,3192],{"class":492,"line":527},[490,3170,609],{"class":551},[490,3172,561],{"class":496},[490,3174,663],{"class":538},[490,3176,567],{"class":496},[490,3178,1755],{"class":650},[490,3180,579],{"class":496},[490,3182,673],{"class":650},[490,3184,579],{"class":496},[490,3186,518],{"class":496},[490,3188,3189],{"class":573},"ACME 科技有限公司",[490,3191,570],{"class":496},[490,3193,603],{"class":496},[490,3195,3196,3198,3200,3203,3205,3208],{"class":492,"line":532},[490,3197,609],{"class":551},[490,3199,561],{"class":496},[490,3201,3202],{"class":538},"Ln",[490,3204,567],{"class":496},[490,3206,3207],{"class":650},"15",[490,3209,603],{"class":496},[490,3211,3212],{"class":492,"line":548},[490,3213,2359],{"class":496},[490,3215,3216,3218,3220,3222,3224],{"class":492,"line":606},[490,3217,1232],{"class":551},[490,3219,561],{"class":496},[490,3221,3059],{"class":538},[490,3223,3133],{"class":496},[490,3225,545],{"class":496},[490,3227,3228,3230,3232,3235,3238,3240],{"class":492,"line":620},[490,3229,609],{"class":551},[490,3231,561],{"class":496},[490,3233,3234],{"class":538},"SetY",[490,3236,3237],{"class":496},"(-",[490,3239,3207],{"class":650},[490,3241,603],{"class":496},[490,3243,3244,3246,3248,3250,3252,3254,3256,3258,3260,3262,3265,3267,3269,3271],{"class":492,"line":656},[490,3245,609],{"class":551},[490,3247,561],{"class":496},[490,3249,627],{"class":538},[490,3251,567],{"class":496},[490,3253,570],{"class":496},[490,3255,634],{"class":573},[490,3257,570],{"class":496},[490,3259,579],{"class":496},[490,3261,518],{"class":496},[490,3263,3264],{"class":573},"I",[490,3266,570],{"class":496},[490,3268,579],{"class":496},[490,3270,1303],{"class":650},[490,3272,603],{"class":496},[490,3274,3275,3277,3279,3281,3283,3285,3287,3289],{"class":492,"line":687},[490,3276,609],{"class":551},[490,3278,561],{"class":496},[490,3280,1293],{"class":538},[490,3282,567],{"class":496},[490,3284,1755],{"class":650},[490,3286,579],{"class":496},[490,3288,673],{"class":650},[490,3290,3291],{"class":496},",\n",[490,3293,3294,3297,3299,3302,3304,3306,3309,3313,3316,3318,3320,3323,3325,3328],{"class":492,"line":708},[490,3295,3296],{"class":551},"        fmt",[490,3298,561],{"class":496},[490,3300,3301],{"class":538},"Sprintf",[490,3303,567],{"class":496},[490,3305,570],{"class":496},[490,3307,3308],{"class":573},"Page ",[490,3310,3312],{"class":3311},"swJcz","%d",[490,3314,3315],{"class":573},"/{nb}",[490,3317,570],{"class":496},[490,3319,579],{"class":496},[490,3321,3322],{"class":551}," pdf",[490,3324,561],{"class":496},[490,3326,3327],{"class":538},"PageNo",[490,3329,3330],{"class":496},"()),\n",[490,3332,3333,3336,3338,3340,3342,3344,3346,3348,3350,3352,3354,3356,3358,3360],{"class":492,"line":799},[490,3334,3335],{"class":496},"        \"\"",[490,3337,579],{"class":496},[490,3339,1327],{"class":650},[490,3341,579],{"class":496},[490,3343,518],{"class":496},[490,3345,1396],{"class":573},[490,3347,570],{"class":496},[490,3349,579],{"class":496},[490,3351,1781],{"class":1341},[490,3353,579],{"class":496},[490,3355,1327],{"class":650},[490,3357,579],{"class":496},[490,3359,600],{"class":496},[490,3361,603],{"class":496},[490,3363,3364],{"class":492,"line":810},[490,3365,2359],{"class":496},[490,3367,3368,3370,3372,3375,3377,3380],{"class":492,"line":829},[490,3369,1232],{"class":551},[490,3371,561],{"class":496},[490,3373,3374],{"class":538},"AliasNbPages",[490,3376,567],{"class":496},[490,3378,3379],{"class":496},"\"\"",[490,3381,603],{"class":496},[490,3383,3384,3386,3388,3390],{"class":492,"line":852},[490,3385,1232],{"class":551},[490,3387,561],{"class":496},[490,3389,614],{"class":538},[490,3391,617],{"class":496},[490,3393,3394],{"class":492,"line":888},[490,3395,3397],{"class":3396},"sHwdD","// ... body ...\n",[18,3399,3400,3403],{},[26,3401,3402],{},"{nb}"," 是 gofpdf 在输出时用总页数重写的哨兵。能用，但得\"知道\"才行。",[18,3405,3406],{},[21,3407,716],{},[481,3409,3411],{"className":483,"code":3410,"language":485,"meta":486,"style":486},"doc := gpdf.NewDocument(\n    gpdf.WithPageSize(document.A4),\n    gpdf.WithMargins(document.UniformEdges(document.Mm(20))),\n)\n\ndoc.Header(func(p *template.PageBuilder) {\n    p.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(\"ACME 科技有限公司\", template.Bold(), template.FontSize(12))\n            c.Line(template.LineColor(pdf.Gray(0.7)))\n            c.Spacer(document.Mm(4))\n        })\n    })\n})\n\ndoc.Footer(func(p *template.PageBuilder) {\n    p.AutoRow(func(r *template.RowBuilder) {\n        r.Col(6, func(c *template.ColBuilder) {\n            c.Text(\"ACME 科技有限公司\",\n                template.FontSize(8), template.TextColor(pdf.Gray(0.5)))\n        })\n        r.Col(6, func(c *template.ColBuilder) {\n            // \"第 X 页 / 共 Y 页\" —— 两者都是占位符，\n            // 分页完成后由布局引擎展开。\n            c.PageNumber(template.AlignRight(),\n                template.FontSize(8), template.TextColor(pdf.Gray(0.5)))\n        })\n    })\n})\n\nfor i := 0; i \u003C 10; i++ {\n    page := doc.AddPage()\n    page.AutoRow(func(r *template.RowBuilder) {\n        r.Col(12, func(c *template.ColBuilder) {\n            c.Text(fmt.Sprintf(\"第 %d 页正文。\", i+1))\n        })\n    })\n}\n",[26,3412,3413,3428,3447,3477,3481,3485,3512,3537,3567,3607,3642,3666,3670,3674,3678,3682,3707,3731,3762,3780,3816,3820,3850,3855,3860,3880,3914,3918,3922,3926,3930,3961,3975,3999,4029,4071,4075,4080],{"__ignoreMap":486},[490,3414,3415,3418,3420,3422,3424,3426],{"class":492,"line":493},[490,3416,3417],{"class":551},"doc ",[490,3419,555],{"class":496},[490,3421,818],{"class":551},[490,3423,561],{"class":496},[490,3425,823],{"class":538},[490,3427,826],{"class":496},[490,3429,3430,3433,3435,3437,3439,3441,3443,3445],{"class":492,"line":504},[490,3431,3432],{"class":551},"    gpdf",[490,3434,561],{"class":496},[490,3436,837],{"class":538},[490,3438,567],{"class":496},[490,3440,842],{"class":551},[490,3442,561],{"class":496},[490,3444,593],{"class":551},[490,3446,849],{"class":496},[490,3448,3449,3451,3453,3455,3457,3459,3461,3463,3465,3467,3469,3471,3473,3475],{"class":492,"line":511},[490,3450,3432],{"class":551},[490,3452,561],{"class":496},[490,3454,859],{"class":538},[490,3456,567],{"class":496},[490,3458,842],{"class":551},[490,3460,561],{"class":496},[490,3462,868],{"class":538},[490,3464,567],{"class":496},[490,3466,842],{"class":551},[490,3468,561],{"class":496},[490,3470,877],{"class":538},[490,3472,567],{"class":496},[490,3474,882],{"class":650},[490,3476,885],{"class":496},[490,3478,3479],{"class":492,"line":527},[490,3480,603],{"class":496},[490,3482,3483],{"class":492,"line":532},[490,3484,508],{"emptyLinePlaceholder":507},[490,3486,3487,3490,3492,3495,3497,3499,3501,3503,3505,3508,3510],{"class":492,"line":548},[490,3488,3489],{"class":551},"doc",[490,3491,561],{"class":496},[490,3493,3494],{"class":538},"Header",[490,3496,927],{"class":496},[490,3498,18],{"class":930},[490,3500,934],{"class":496},[490,3502,937],{"class":500},[490,3504,561],{"class":496},[490,3506,3507],{"class":500},"PageBuilder",[490,3509,207],{"class":496},[490,3511,545],{"class":496},[490,3513,3514,3517,3519,3521,3523,3525,3527,3529,3531,3533,3535],{"class":492,"line":606},[490,3515,3516],{"class":551},"    p",[490,3518,561],{"class":496},[490,3520,924],{"class":538},[490,3522,927],{"class":496},[490,3524,931],{"class":930},[490,3526,934],{"class":496},[490,3528,937],{"class":500},[490,3530,561],{"class":496},[490,3532,942],{"class":500},[490,3534,207],{"class":496},[490,3536,545],{"class":496},[490,3538,3539,3541,3543,3545,3547,3549,3551,3553,3555,3557,3559,3561,3563,3565],{"class":492,"line":620},[490,3540,952],{"class":551},[490,3542,561],{"class":496},[490,3544,957],{"class":538},[490,3546,567],{"class":496},[490,3548,962],{"class":650},[490,3550,579],{"class":496},[490,3552,967],{"class":496},[490,3554,970],{"class":930},[490,3556,934],{"class":496},[490,3558,937],{"class":500},[490,3560,561],{"class":496},[490,3562,979],{"class":500},[490,3564,207],{"class":496},[490,3566,545],{"class":496},[490,3568,3569,3571,3573,3575,3577,3579,3581,3583,3585,3587,3589,3591,3594,3596,3598,3600,3602,3604],{"class":492,"line":656},[490,3570,989],{"class":551},[490,3572,561],{"class":496},[490,3574,994],{"class":538},[490,3576,567],{"class":496},[490,3578,570],{"class":496},[490,3580,3189],{"class":573},[490,3582,570],{"class":496},[490,3584,579],{"class":496},[490,3586,1007],{"class":551},[490,3588,561],{"class":496},[490,3590,1027],{"class":538},[490,3592,3593],{"class":496},"(),",[490,3595,1007],{"class":551},[490,3597,561],{"class":496},[490,3599,1012],{"class":538},[490,3601,567],{"class":496},[490,3603,962],{"class":650},[490,3605,3606],{"class":496},"))\n",[490,3608,3609,3611,3613,3616,3618,3620,3622,3625,3627,3629,3631,3634,3636,3639],{"class":492,"line":687},[490,3610,989],{"class":551},[490,3612,561],{"class":496},[490,3614,3615],{"class":538},"Line",[490,3617,567],{"class":496},[490,3619,937],{"class":551},[490,3621,561],{"class":496},[490,3623,3624],{"class":538},"LineColor",[490,3626,567],{"class":496},[490,3628,1232],{"class":551},[490,3630,561],{"class":496},[490,3632,3633],{"class":538},"Gray",[490,3635,567],{"class":496},[490,3637,3638],{"class":650},"0.7",[490,3640,3641],{"class":496},")))\n",[490,3643,3644,3646,3648,3651,3653,3655,3657,3659,3661,3664],{"class":492,"line":708},[490,3645,989],{"class":551},[490,3647,561],{"class":496},[490,3649,3650],{"class":538},"Spacer",[490,3652,567],{"class":496},[490,3654,842],{"class":551},[490,3656,561],{"class":496},[490,3658,877],{"class":538},[490,3660,567],{"class":496},[490,3662,3663],{"class":650},"4",[490,3665,3606],{"class":496},[490,3667,3668],{"class":492,"line":799},[490,3669,1036],{"class":496},[490,3671,3672],{"class":492,"line":810},[490,3673,1042],{"class":496},[490,3675,3676],{"class":492,"line":829},[490,3677,2359],{"class":496},[490,3679,3680],{"class":492,"line":852},[490,3681,508],{"emptyLinePlaceholder":507},[490,3683,3684,3686,3688,3691,3693,3695,3697,3699,3701,3703,3705],{"class":492,"line":888},[490,3685,3489],{"class":551},[490,3687,561],{"class":496},[490,3689,3690],{"class":538},"Footer",[490,3692,927],{"class":496},[490,3694,18],{"class":930},[490,3696,934],{"class":496},[490,3698,937],{"class":500},[490,3700,561],{"class":496},[490,3702,3507],{"class":500},[490,3704,207],{"class":496},[490,3706,545],{"class":496},[490,3708,3709,3711,3713,3715,3717,3719,3721,3723,3725,3727,3729],{"class":492,"line":894},[490,3710,3516],{"class":551},[490,3712,561],{"class":496},[490,3714,924],{"class":538},[490,3716,927],{"class":496},[490,3718,931],{"class":930},[490,3720,934],{"class":496},[490,3722,937],{"class":500},[490,3724,561],{"class":496},[490,3726,942],{"class":500},[490,3728,207],{"class":496},[490,3730,545],{"class":496},[490,3732,3733,3735,3737,3739,3741,3744,3746,3748,3750,3752,3754,3756,3758,3760],{"class":492,"line":899},[490,3734,952],{"class":551},[490,3736,561],{"class":496},[490,3738,957],{"class":538},[490,3740,567],{"class":496},[490,3742,3743],{"class":650},"6",[490,3745,579],{"class":496},[490,3747,967],{"class":496},[490,3749,970],{"class":930},[490,3751,934],{"class":496},[490,3753,937],{"class":500},[490,3755,561],{"class":496},[490,3757,979],{"class":500},[490,3759,207],{"class":496},[490,3761,545],{"class":496},[490,3763,3764,3766,3768,3770,3772,3774,3776,3778],{"class":492,"line":916},[490,3765,989],{"class":551},[490,3767,561],{"class":496},[490,3769,994],{"class":538},[490,3771,567],{"class":496},[490,3773,570],{"class":496},[490,3775,3189],{"class":573},[490,3777,570],{"class":496},[490,3779,3291],{"class":496},[490,3781,3782,3784,3786,3788,3790,3793,3795,3797,3799,3801,3803,3805,3807,3809,3811,3814],{"class":492,"line":949},[490,3783,2263],{"class":551},[490,3785,561],{"class":496},[490,3787,1012],{"class":538},[490,3789,567],{"class":496},[490,3791,3792],{"class":650},"8",[490,3794,1020],{"class":496},[490,3796,1007],{"class":551},[490,3798,561],{"class":496},[490,3800,2279],{"class":538},[490,3802,567],{"class":496},[490,3804,1232],{"class":551},[490,3806,561],{"class":496},[490,3808,3633],{"class":538},[490,3810,567],{"class":496},[490,3812,3813],{"class":650},"0.5",[490,3815,3641],{"class":496},[490,3817,3818],{"class":492,"line":986},[490,3819,1036],{"class":496},[490,3821,3822,3824,3826,3828,3830,3832,3834,3836,3838,3840,3842,3844,3846,3848],{"class":492,"line":1033},[490,3823,952],{"class":551},[490,3825,561],{"class":496},[490,3827,957],{"class":538},[490,3829,567],{"class":496},[490,3831,3743],{"class":650},[490,3833,579],{"class":496},[490,3835,967],{"class":496},[490,3837,970],{"class":930},[490,3839,934],{"class":496},[490,3841,937],{"class":500},[490,3843,561],{"class":496},[490,3845,979],{"class":500},[490,3847,207],{"class":496},[490,3849,545],{"class":496},[490,3851,3852],{"class":492,"line":1039},[490,3853,3854],{"class":3396},"            // \"第 X 页 / 共 Y 页\" —— 两者都是占位符，\n",[490,3856,3857],{"class":492,"line":1045},[490,3858,3859],{"class":3396},"            // 分页完成后由布局引擎展开。\n",[490,3861,3862,3864,3866,3869,3871,3873,3875,3878],{"class":492,"line":1050},[490,3863,989],{"class":551},[490,3865,561],{"class":496},[490,3867,3868],{"class":538},"PageNumber",[490,3870,567],{"class":496},[490,3872,937],{"class":551},[490,3874,561],{"class":496},[490,3876,3877],{"class":538},"AlignRight",[490,3879,2270],{"class":496},[490,3881,3882,3884,3886,3888,3890,3892,3894,3896,3898,3900,3902,3904,3906,3908,3910,3912],{"class":492,"line":1072},[490,3883,2263],{"class":551},[490,3885,561],{"class":496},[490,3887,1012],{"class":538},[490,3889,567],{"class":496},[490,3891,3792],{"class":650},[490,3893,1020],{"class":496},[490,3895,1007],{"class":551},[490,3897,561],{"class":496},[490,3899,2279],{"class":538},[490,3901,567],{"class":496},[490,3903,1232],{"class":551},[490,3905,561],{"class":496},[490,3907,3633],{"class":538},[490,3909,567],{"class":496},[490,3911,3813],{"class":650},[490,3913,3641],{"class":496},[490,3915,3916],{"class":492,"line":1088},[490,3917,1036],{"class":496},[490,3919,3920],{"class":492,"line":1106},[490,3921,1042],{"class":496},[490,3923,3924],{"class":492,"line":1112},[490,3925,2359],{"class":496},[490,3927,3928],{"class":492,"line":1158},[490,3929,508],{"emptyLinePlaceholder":507},[490,3931,3932,3934,3937,3939,3941,3944,3946,3949,3951,3953,3956,3959],{"class":492,"line":1173},[490,3933,1710],{"class":514},[490,3935,3936],{"class":551}," i ",[490,3938,555],{"class":496},[490,3940,1327],{"class":650},[490,3942,3943],{"class":496},";",[490,3945,3936],{"class":551},[490,3947,3948],{"class":496},"\u003C",[490,3950,673],{"class":650},[490,3952,3943],{"class":496},[490,3954,3955],{"class":551}," i",[490,3957,3958],{"class":496},"++",[490,3960,545],{"class":496},[490,3962,3963,3965,3967,3969,3971,3973],{"class":492,"line":1178},[490,3964,902],{"class":551},[490,3966,555],{"class":496},[490,3968,907],{"class":551},[490,3970,561],{"class":496},[490,3972,614],{"class":538},[490,3974,617],{"class":496},[490,3976,3977,3979,3981,3983,3985,3987,3989,3991,3993,3995,3997],{"class":492,"line":2971},[490,3978,919],{"class":551},[490,3980,561],{"class":496},[490,3982,924],{"class":538},[490,3984,927],{"class":496},[490,3986,931],{"class":930},[490,3988,934],{"class":496},[490,3990,937],{"class":500},[490,3992,561],{"class":496},[490,3994,942],{"class":500},[490,3996,207],{"class":496},[490,3998,545],{"class":496},[490,4000,4001,4003,4005,4007,4009,4011,4013,4015,4017,4019,4021,4023,4025,4027],{"class":492,"line":2976},[490,4002,952],{"class":551},[490,4004,561],{"class":496},[490,4006,957],{"class":538},[490,4008,567],{"class":496},[490,4010,962],{"class":650},[490,4012,579],{"class":496},[490,4014,967],{"class":496},[490,4016,970],{"class":930},[490,4018,934],{"class":496},[490,4020,937],{"class":500},[490,4022,561],{"class":496},[490,4024,979],{"class":500},[490,4026,207],{"class":496},[490,4028,545],{"class":496},[490,4030,4031,4033,4035,4037,4039,4042,4044,4046,4048,4050,4053,4055,4058,4060,4062,4064,4067,4069],{"class":492,"line":2996},[490,4032,989],{"class":551},[490,4034,561],{"class":496},[490,4036,994],{"class":538},[490,4038,567],{"class":496},[490,4040,4041],{"class":551},"fmt",[490,4043,561],{"class":496},[490,4045,3301],{"class":538},[490,4047,567],{"class":496},[490,4049,570],{"class":496},[490,4051,4052],{"class":573},"第 ",[490,4054,3312],{"class":3311},[490,4056,4057],{"class":573}," 页正文。",[490,4059,570],{"class":496},[490,4061,579],{"class":496},[490,4063,3955],{"class":551},[490,4065,4066],{"class":496},"+",[490,4068,1320],{"class":650},[490,4070,3606],{"class":496},[490,4072,4073],{"class":492,"line":3024},[490,4074,1036],{"class":496},[490,4076,4078],{"class":492,"line":4077},37,[490,4079,1042],{"class":496},[490,4081,4083],{"class":492,"line":4082},38,[490,4084,711],{"class":496},[18,4086,4087,4089,4090,4093,4094,4096,4097,4100],{},[26,4088,3868],{}," 和 ",[26,4091,4092],{},"TotalPages"," 是占位符，分页完成、布局引擎知道总页数后才展开。不需要 ",[26,4095,3402],{}," 哨兵，也不需要 ",[26,4098,4099],{},"SetY(-15)"," 把页脚钉在底部 —— 页脚就是一棵树，引擎每页自动为它预留空间。",[13,4102,4104],{"id":4103},"before-after-5给-http-handler-返回字节流","Before / After 5：给 HTTP handler 返回字节流",[18,4106,4107,4108,4110,4111,4114,4115,4118],{},"实际生产 gofpdf 代码大多不写文件，而是写到 ",[26,4109,1203],{}," —— 一般是返回 ",[26,4112,4113],{},"application/pdf"," 的 ",[26,4116,4117],{},"http.ResponseWriter","。这组里 gpdf 的 API 最接近 gofpdf。",[18,4120,4121],{},[21,4122,479],{},[481,4124,4126],{"className":483,"code":4125,"language":485,"meta":486,"style":486},"func handler(w http.ResponseWriter, r *http.Request) {\n    pdf := gofpdf.New(\"P\", \"mm\", \"A4\", \"\")\n    pdf.AddPage()\n    pdf.SetFont(\"Arial\", \"\", 12)\n    pdf.Cell(0, 10, \"生成时间: \"+time.Now().Format(time.RFC3339))\n\n    w.Header().Set(\"Content-Type\", \"application/pdf\")\n    if err := pdf.Output(w); err != nil {\n        http.Error(w, err.Error(), 500)\n    }\n}\n",[26,4127,4128,4167,4209,4219,4245,4297,4301,4334,4363,4393,4397],{"__ignoreMap":486},[490,4129,4130,4132,4135,4137,4140,4143,4145,4148,4150,4153,4155,4158,4160,4163,4165],{"class":492,"line":493},[490,4131,535],{"class":496},[490,4133,4134],{"class":538}," handler",[490,4136,567],{"class":496},[490,4138,4139],{"class":930},"w",[490,4141,4142],{"class":500}," http",[490,4144,561],{"class":496},[490,4146,4147],{"class":500},"ResponseWriter",[490,4149,579],{"class":496},[490,4151,4152],{"class":930}," r",[490,4154,934],{"class":496},[490,4156,4157],{"class":500},"http",[490,4159,561],{"class":496},[490,4161,4162],{"class":500},"Request",[490,4164,207],{"class":496},[490,4166,545],{"class":496},[490,4168,4169,4171,4173,4175,4177,4179,4181,4183,4185,4187,4189,4191,4193,4195,4197,4199,4201,4203,4205,4207],{"class":492,"line":504},[490,4170,552],{"class":551},[490,4172,555],{"class":496},[490,4174,558],{"class":551},[490,4176,561],{"class":496},[490,4178,564],{"class":538},[490,4180,567],{"class":496},[490,4182,570],{"class":496},[490,4184,574],{"class":573},[490,4186,570],{"class":496},[490,4188,579],{"class":496},[490,4190,518],{"class":496},[490,4192,584],{"class":573},[490,4194,570],{"class":496},[490,4196,579],{"class":496},[490,4198,518],{"class":496},[490,4200,593],{"class":573},[490,4202,570],{"class":496},[490,4204,579],{"class":496},[490,4206,600],{"class":496},[490,4208,603],{"class":496},[490,4210,4211,4213,4215,4217],{"class":492,"line":511},[490,4212,609],{"class":551},[490,4214,561],{"class":496},[490,4216,614],{"class":538},[490,4218,617],{"class":496},[490,4220,4221,4223,4225,4227,4229,4231,4233,4235,4237,4239,4241,4243],{"class":492,"line":527},[490,4222,609],{"class":551},[490,4224,561],{"class":496},[490,4226,627],{"class":538},[490,4228,567],{"class":496},[490,4230,570],{"class":496},[490,4232,634],{"class":573},[490,4234,570],{"class":496},[490,4236,579],{"class":496},[490,4238,600],{"class":496},[490,4240,579],{"class":496},[490,4242,3164],{"class":650},[490,4244,603],{"class":496},[490,4246,4247,4249,4251,4253,4255,4257,4259,4261,4263,4265,4268,4270,4272,4275,4277,4280,4283,4286,4288,4290,4292,4295],{"class":492,"line":532},[490,4248,609],{"class":551},[490,4250,561],{"class":496},[490,4252,663],{"class":538},[490,4254,567],{"class":496},[490,4256,1755],{"class":650},[490,4258,579],{"class":496},[490,4260,673],{"class":650},[490,4262,579],{"class":496},[490,4264,518],{"class":496},[490,4266,4267],{"class":573},"生成时间: ",[490,4269,570],{"class":496},[490,4271,4066],{"class":496},[490,4273,4274],{"class":551},"time",[490,4276,561],{"class":496},[490,4278,4279],{"class":538},"Now",[490,4281,4282],{"class":496},"().",[490,4284,4285],{"class":538},"Format",[490,4287,567],{"class":496},[490,4289,4274],{"class":551},[490,4291,561],{"class":496},[490,4293,4294],{"class":551},"RFC3339",[490,4296,3606],{"class":496},[490,4298,4299],{"class":492,"line":548},[490,4300,508],{"emptyLinePlaceholder":507},[490,4302,4303,4306,4308,4310,4312,4315,4317,4319,4322,4324,4326,4328,4330,4332],{"class":492,"line":606},[490,4304,4305],{"class":551},"    w",[490,4307,561],{"class":496},[490,4309,3494],{"class":538},[490,4311,4282],{"class":496},[490,4313,4314],{"class":538},"Set",[490,4316,567],{"class":496},[490,4318,570],{"class":496},[490,4320,4321],{"class":573},"Content-Type",[490,4323,570],{"class":496},[490,4325,579],{"class":496},[490,4327,518],{"class":496},[490,4329,4113],{"class":573},[490,4331,570],{"class":496},[490,4333,603],{"class":496},[490,4335,4336,4338,4340,4342,4344,4346,4349,4351,4353,4355,4357,4359,4361],{"class":492,"line":620},[490,4337,1075],{"class":514},[490,4339,1058],{"class":551},[490,4341,555],{"class":496},[490,4343,3322],{"class":551},[490,4345,561],{"class":496},[490,4347,4348],{"class":538},"Output",[490,4350,567],{"class":496},[490,4352,4139],{"class":551},[490,4354,1147],{"class":496},[490,4356,1058],{"class":551},[490,4358,1080],{"class":496},[490,4360,1083],{"class":496},[490,4362,545],{"class":496},[490,4364,4365,4368,4370,4373,4375,4377,4379,4382,4384,4386,4388,4391],{"class":492,"line":656},[490,4366,4367],{"class":551},"        http",[490,4369,561],{"class":496},[490,4371,4372],{"class":538},"Error",[490,4374,567],{"class":496},[490,4376,4139],{"class":551},[490,4378,579],{"class":496},[490,4380,4381],{"class":551}," err",[490,4383,561],{"class":496},[490,4385,4372],{"class":538},[490,4387,3593],{"class":496},[490,4389,4390],{"class":650}," 500",[490,4392,603],{"class":496},[490,4394,4395],{"class":492,"line":687},[490,4396,1109],{"class":496},[490,4398,4399],{"class":492,"line":708},[490,4400,711],{"class":496},[18,4402,4403],{},[21,4404,716],{},[481,4406,4408],{"className":483,"code":4407,"language":485,"meta":486,"style":486},"func handler(w http.ResponseWriter, r *http.Request) {\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(\"生成时间: \" + time.Now().Format(time.RFC3339))\n        })\n    })\n\n    w.Header().Set(\"Content-Type\", \"application/pdf\")\n    if err := doc.Render(w); err != nil {\n        http.Error(w, err.Error(), 500)\n    }\n}\n",[26,4409,4410,4442,4456,4474,4504,4508,4512,4526,4550,4580,4620,4624,4628,4632,4662,4691,4717,4721],{"__ignoreMap":486},[490,4411,4412,4414,4416,4418,4420,4422,4424,4426,4428,4430,4432,4434,4436,4438,4440],{"class":492,"line":493},[490,4413,535],{"class":496},[490,4415,4134],{"class":538},[490,4417,567],{"class":496},[490,4419,4139],{"class":930},[490,4421,4142],{"class":500},[490,4423,561],{"class":496},[490,4425,4147],{"class":500},[490,4427,579],{"class":496},[490,4429,4152],{"class":930},[490,4431,934],{"class":496},[490,4433,4157],{"class":500},[490,4435,561],{"class":496},[490,4437,4162],{"class":500},[490,4439,207],{"class":496},[490,4441,545],{"class":496},[490,4443,4444,4446,4448,4450,4452,4454],{"class":492,"line":504},[490,4445,813],{"class":551},[490,4447,555],{"class":496},[490,4449,818],{"class":551},[490,4451,561],{"class":496},[490,4453,823],{"class":538},[490,4455,826],{"class":496},[490,4457,4458,4460,4462,4464,4466,4468,4470,4472],{"class":492,"line":511},[490,4459,832],{"class":551},[490,4461,561],{"class":496},[490,4463,837],{"class":538},[490,4465,567],{"class":496},[490,4467,842],{"class":551},[490,4469,561],{"class":496},[490,4471,593],{"class":551},[490,4473,849],{"class":496},[490,4475,4476,4478,4480,4482,4484,4486,4488,4490,4492,4494,4496,4498,4500,4502],{"class":492,"line":527},[490,4477,832],{"class":551},[490,4479,561],{"class":496},[490,4481,859],{"class":538},[490,4483,567],{"class":496},[490,4485,842],{"class":551},[490,4487,561],{"class":496},[490,4489,868],{"class":538},[490,4491,567],{"class":496},[490,4493,842],{"class":551},[490,4495,561],{"class":496},[490,4497,877],{"class":538},[490,4499,567],{"class":496},[490,4501,882],{"class":650},[490,4503,885],{"class":496},[490,4505,4506],{"class":492,"line":532},[490,4507,891],{"class":496},[490,4509,4510],{"class":492,"line":548},[490,4511,508],{"emptyLinePlaceholder":507},[490,4513,4514,4516,4518,4520,4522,4524],{"class":492,"line":606},[490,4515,902],{"class":551},[490,4517,555],{"class":496},[490,4519,907],{"class":551},[490,4521,561],{"class":496},[490,4523,614],{"class":538},[490,4525,617],{"class":496},[490,4527,4528,4530,4532,4534,4536,4538,4540,4542,4544,4546,4548],{"class":492,"line":620},[490,4529,919],{"class":551},[490,4531,561],{"class":496},[490,4533,924],{"class":538},[490,4535,927],{"class":496},[490,4537,931],{"class":930},[490,4539,934],{"class":496},[490,4541,937],{"class":500},[490,4543,561],{"class":496},[490,4545,942],{"class":500},[490,4547,207],{"class":496},[490,4549,545],{"class":496},[490,4551,4552,4554,4556,4558,4560,4562,4564,4566,4568,4570,4572,4574,4576,4578],{"class":492,"line":656},[490,4553,952],{"class":551},[490,4555,561],{"class":496},[490,4557,957],{"class":538},[490,4559,567],{"class":496},[490,4561,962],{"class":650},[490,4563,579],{"class":496},[490,4565,967],{"class":496},[490,4567,970],{"class":930},[490,4569,934],{"class":496},[490,4571,937],{"class":500},[490,4573,561],{"class":496},[490,4575,979],{"class":500},[490,4577,207],{"class":496},[490,4579,545],{"class":496},[490,4581,4582,4584,4586,4588,4590,4592,4594,4596,4599,4602,4604,4606,4608,4610,4612,4614,4616,4618],{"class":492,"line":687},[490,4583,989],{"class":551},[490,4585,561],{"class":496},[490,4587,994],{"class":538},[490,4589,567],{"class":496},[490,4591,570],{"class":496},[490,4593,4267],{"class":573},[490,4595,570],{"class":496},[490,4597,4598],{"class":496}," +",[490,4600,4601],{"class":551}," time",[490,4603,561],{"class":496},[490,4605,4279],{"class":538},[490,4607,4282],{"class":496},[490,4609,4285],{"class":538},[490,4611,567],{"class":496},[490,4613,4274],{"class":551},[490,4615,561],{"class":496},[490,4617,4294],{"class":551},[490,4619,3606],{"class":496},[490,4621,4622],{"class":492,"line":708},[490,4623,1036],{"class":496},[490,4625,4626],{"class":492,"line":799},[490,4627,1042],{"class":496},[490,4629,4630],{"class":492,"line":810},[490,4631,508],{"emptyLinePlaceholder":507},[490,4633,4634,4636,4638,4640,4642,4644,4646,4648,4650,4652,4654,4656,4658,4660],{"class":492,"line":829},[490,4635,4305],{"class":551},[490,4637,561],{"class":496},[490,4639,3494],{"class":538},[490,4641,4282],{"class":496},[490,4643,4314],{"class":538},[490,4645,567],{"class":496},[490,4647,570],{"class":496},[490,4649,4321],{"class":573},[490,4651,570],{"class":496},[490,4653,579],{"class":496},[490,4655,518],{"class":496},[490,4657,4113],{"class":573},[490,4659,570],{"class":496},[490,4661,603],{"class":496},[490,4663,4664,4666,4668,4670,4672,4674,4677,4679,4681,4683,4685,4687,4689],{"class":492,"line":852},[490,4665,1075],{"class":514},[490,4667,1058],{"class":551},[490,4669,555],{"class":496},[490,4671,907],{"class":551},[490,4673,561],{"class":496},[490,4675,4676],{"class":538},"Render",[490,4678,567],{"class":496},[490,4680,4139],{"class":551},[490,4682,1147],{"class":496},[490,4684,1058],{"class":551},[490,4686,1080],{"class":496},[490,4688,1083],{"class":496},[490,4690,545],{"class":496},[490,4692,4693,4695,4697,4699,4701,4703,4705,4707,4709,4711,4713,4715],{"class":492,"line":888},[490,4694,4367],{"class":551},[490,4696,561],{"class":496},[490,4698,4372],{"class":538},[490,4700,567],{"class":496},[490,4702,4139],{"class":551},[490,4704,579],{"class":496},[490,4706,4381],{"class":551},[490,4708,561],{"class":496},[490,4710,4372],{"class":538},[490,4712,3593],{"class":496},[490,4714,4390],{"class":650},[490,4716,603],{"class":496},[490,4718,4719],{"class":492,"line":894},[490,4720,1109],{"class":496},[490,4722,4723],{"class":492,"line":899},[490,4724,711],{"class":496},[18,4726,4727,4728,4730,4731,4734,4735,4737,4738,3071],{},"形态一样。",[26,4729,425],{}," 直接把 PDF 流进响应。如果要带 ",[26,4732,4733],{},"Content-Length","，先调 ",[26,4736,1195],{}," 拿字节切片再 ",[26,4739,4740],{},"len()",[13,4742,4744],{"id":4743},"够快到底是多快","\"够快\"到底是多快？",[18,4746,4747,4748,4750,4751,4754],{},"gpdf 在实际负载上",[21,4749,36],{},"。下表数据来自 ",[26,4752,4753],{},"_benchmark/benchmark_test.go","，Apple M1、Go 1.25。",[148,4756,4757,4774],{},[151,4758,4759],{},[154,4760,4761,4764,4766,4768,4771],{},[157,4762,4763],{},"基准",[157,4765,23],{},[157,4767,162],{},[157,4769,4770],{},"gopdf",[157,4772,4773],{},"Maroto v2",[166,4775,4776,4795,4814,4832],{},[154,4777,4778,4781,4786,4789,4792],{},[171,4779,4780],{},"单页",[171,4782,4783],{},[21,4784,4785],{},"13 µs",[171,4787,4788],{},"132 µs",[171,4790,4791],{},"423 µs",[171,4793,4794],{},"237 µs",[154,4796,4797,4800,4805,4808,4811],{},[171,4798,4799],{},"4×10 表格",[171,4801,4802],{},[21,4803,4804],{},"108 µs",[171,4806,4807],{},"241 µs",[171,4809,4810],{},"835 µs",[171,4812,4813],{},"8.6 ms",[154,4815,4816,4819,4824,4827,4829],{},[171,4817,4818],{},"100 页文档",[171,4820,4821],{},[21,4822,4823],{},"683 µs",[171,4825,4826],{},"11.7 ms",[171,4828,4813],{},[171,4830,4831],{},"19.8 ms",[154,4833,4834,4837,4842,4845,4848],{},[171,4835,4836],{},"复杂 CJK 发票",[171,4838,4839],{},[21,4840,4841],{},"133 µs",[171,4843,4844],{},"254 µs",[171,4846,4847],{},"997 µs",[171,4849,4850],{},"10.4 ms",[18,4852,4853],{},"不是合成数。表格基准是 4 列 10 行发票明细，100 页基准是带重复页眉和页码的报表 —— 正是生产代码的形态。",[18,4855,4856],{},"顺便说一下含义。13 µs/单页 = 单核每秒 7.5 万张 hello-world PDF；108 µs/带表页 = 每秒约 9,000 张发票。重点不是炫耀，而是你可以不用再纠结 \"PDF 生成要不要缓存？是不是得丢进异步队列？\" 这种事。多数场景下，请求链路里同步生成就够。",[13,4858,4859],{"id":4859},"迁移要放弃的东西",[18,4861,4862],{},"指南不该掩盖真实差距。gpdf 目前相对 gofpdf 欠缺的：",[4864,4865,4866,4875,4891,4897],"ul",{},[110,4867,4868,3071,4871,4874],{},[21,4869,4870],{},"任意角度的直线、贝塞尔曲线、复杂路径",[26,4872,4873],{},"c.Line()"," 画的是跨列的水平线。CAD 图或自定义图表几何，gpdf 还没到。（但图表以图像形式预渲染嵌入是完全没问题的。）",[110,4876,4877,4882,4883,4885,4886,3067,4888,4890],{},[21,4878,4879,4881],{},[26,4880,32],{}," 与绝对光标","。能用 ",[26,4884,346],{}," 做绝对定位，但如果现有代码是 2,000 行 ",[26,4887,32],{},[26,4889,663],{},"，迁移基本等同重写。好处是重写后通常只有原来一半长。",[110,4892,4893,4896],{},[21,4894,4895],{},"AcroForm 可填写表单","。gpdf 还不生成可填字段。如果你的 PDF 是给用户在阅读器里填写的模板，暂时留在支持 AcroForm 的库上。",[110,4898,4899,4902],{},[21,4900,4901],{},"注释与书签","。基础大纲有，丰富注释没有。",[18,4904,4905],{},"如果这些都不卡你，迁移一气呵成。如果卡，开一个 Issue —— 路线图是由需求驱动的。",[13,4907,4909],{"id":4908},"faq","FAQ",[18,4911,4912,4915],{},[21,4913,4914],{},"gpdf 是 gofpdf 的 fork 吗？","\n不是。gpdf 是纯 Go 从零重写的。PDF 线格式、布局引擎、TrueType 子集化器 —— 全部独立实现，与 gofpdf 及其 fork 没有代码血缘。必须重写而非 fork，是因为 gofpdf 的架构建立在\"单一可变光标\"上，声明式栅格塞不进去而不把现有调用全部打碎。",[18,4917,4918,4921,4922,4925,4926,4929,4930,4933,4934,4937],{},[21,4919,4920],{},"gpdf 有外部依赖吗？","\n核心零依赖。",[26,4923,4924],{},"go get github.com/gpdf-dev/gpdf"," 后 ",[26,4927,4928],{},"go mod graph | grep gpdf"," 只返回一行。",[26,4931,4932],{},"gpdf-pro"," 扩展（HTML→PDF、AES 加密、数字签名、PDF/A）会因 HTML 解析引入 ",[26,4935,4936],{},"golang.org/x/net","，但那是可选，迁移用不到。",[18,4939,4940,4943,4944,4947],{},[21,4941,4942],{},"CGO 呢？gofpdf 是 CGO-free 的，gpdf 呢？","\n同样纯 Go、无 CGO。",[26,4945,4946],{},"GOOS=linux GOARCH=arm64 go build"," 就能交叉编译出静态二进制。这对 distroless 和 Alpine 镜像尤其重要 —— 没有 CGO 工具链，镜像大小能差一半。",[18,4949,4950,4956,4957,4959],{},[21,4951,4952,4953,4955],{},"我现有 gofpdf 代码里到处是 ",[26,4954,32],{}," 绝对定位。能不重写就迁过来吗？","\n可以包一层 ",[26,4958,346],{}," 做类似感觉。但如果整个代码围绕光标操作组织，迁到布局引擎模型是心智切换而非语法切换。多数团队发现重写后比原版更短。",[18,4961,4962,4965,4966,4968],{},[21,4963,4964],{},"增值税发票、合规归档怎么办？","\n时间戳和数字签名在 ",[26,4967,4932],{}," 里实现中。有具体需求，开 Issue 提优先级。",[18,4970,4971,4974],{},[21,4972,4973],{},"要是 go-pdf/fpdf 又恢复维护呢？","\n那就多一个选择。gpdf 的赌注不是\"gofpdf 永远归档\"，而是\"基于光标 + 单字节字体 + 无原生 CJK 的架构，谁维护都是死胡同\"。2026 年的 PDF 生成更像搭网页而非驱动绘图仪，API 应该反映这一点。",[13,4976,4978],{"id":4977},"试试-gpdf","试试 gpdf",[18,4980,4981],{},"gpdf 是 Go 的 PDF 生成库。MIT 协议、零外部依赖、原生 CJK。",[481,4983,4987],{"className":4984,"code":4985,"language":4986,"meta":486,"style":486},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[26,4988,4989],{"__ignoreMap":486},[490,4990,4991,4993,4996],{"class":492,"line":493},[490,4992,485],{"class":500},[490,4994,4995],{"class":573}," get",[490,4997,4998],{"class":573}," github.com/gpdf-dev/gpdf\n",[18,5000,5001,5008,5009],{},[5002,5003,5007],"a",{"href":5004,"rel":5005},"https://github.com/gpdf-dev/gpdf",[5006],"nofollow","⭐ 在 GitHub 加星"," · ",[5002,5010,5013],{"href":5011,"rel":5012},"https://gpdf.dev/zh/docs/quickstart",[5006],"阅读文档",[13,5015,5016],{"id":5016},"延伸阅读",[4864,5018,5019,5025,5030],{},[110,5020,5021,5022],{},"12 栅格在 gpdf 里是怎么工作的 ",[201,5023,5024],{},"(即将发布)",[110,5026,5027,5028],{},"如何在 gpdf 里嵌入中文字体 ",[201,5029,5024],{},[110,5031,5032,5036,5037],{},[5002,5033,5035],{"href":5011,"rel":5034},[5006],"Quickstart"," —— 5 分钟上手，含 ",[26,5038,5039],{},"go.mod",[5041,5042,5043],"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 .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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);}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 .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":486,"searchDepth":504,"depth":504,"links":5045},[5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059],{"id":15,"depth":504,"text":16},{"id":71,"depth":504,"text":72},{"id":101,"depth":504,"text":102},{"id":142,"depth":504,"text":143},{"id":470,"depth":504,"text":471},{"id":1207,"depth":504,"text":1208},{"id":2382,"depth":504,"text":2383},{"id":3049,"depth":504,"text":3050},{"id":4103,"depth":504,"text":4104},{"id":4743,"depth":504,"text":4744},{"id":4859,"depth":504,"text":4859},{"id":4908,"depth":504,"text":4909},{"id":4977,"depth":504,"text":4978},{"id":5016,"depth":504,"text":5016},"2026-04-14","gofpdf 于 2021 年归档，后继 go-pdf/fpdf 也在 2025 年停止。纯 Go、零依赖、原生 CJK 的 gpdf 迁移指南。",false,"md",{"name":5065,"totalTime":5066,"tools":5067,"steps":5069},"将 Go 项目从 gofpdf 迁移到 gpdf","PT30M",[5068],"Go 1.22+",[5070,5073,5076,5079,5082,5085],{"name":5071,"text":5072},"替换 import 路径","把 2021 年归档的 github.com/jung-kurt/gofpdf 和 2025 年停止的 github.com/go-pdf/fpdf 换成 github.com/gpdf-dev/gpdf、github.com/gpdf-dev/gpdf/document、github.com/gpdf-dev/gpdf/template。",{"name":5074,"text":5075},"用 builder 构建文档，替代游标","调用 gpdf.NewDocument 并传入 WithPageSize / WithMargins / WithFont。不再用 SetXY 推动游标，而是用 doc.AddPage() 添加页面，通过 RowBuilder 和 ColBuilder 声明内容。",{"name":5077,"text":5078},"把 Cell / MultiCell 换成声明式的 Text","把 pdf.Cell 和 pdf.MultiCell 换成列里的 c.Text(...)。文本会在列边界自动换行，因此 MultiCell 的尾部标志可以去掉。字号、粗体、颜色都作为 per-text 选项传入。",{"name":5080,"text":5081},"通过 WithFont 注册 CJK 字体","对于中文、日文、韩文，把 pdf.AddUTF8Font 换成在文档构建时传入 gpdf.WithFont(name, ttfBytes)。不必维护 TTF 路径或 UTF-8 标志，子集嵌入由 gpdf 自动完成。",{"name":5083,"text":5084},"用行和列重写表格","去掉手动管理列宽的 Cell 嵌套循环，在 AutoRow 内用 row.Col(n, fn) 构建表格行。12 栅格会替你计算宽度并处理分页。",{"name":5086,"text":5087},"切换输出调用","把 pdf.OutputFileAndClose(path) 换成 doc.Generate() 取得字节，再用 os.WriteFile(path, data, 0o644) 写入。想直接写到 io.Writer 就用 doc.Render(w)。",null,{},"/zh/blog/gofpdf-migration",{"title":5,"description":5061},"zh/blog/001.gofpdf-migration",[5094,5095,5096,5097],"migration","comparison","tutorial","cjk","mlCYWU2UEcAx2swleLfU-F_R-F0JN-3obO81vzsn2n4",1776529262524]