[{"data":1,"prerenderedAt":5096},["ShallowReactive",2],{"blog-es-gofpdf-migration":3},{"id":4,"title":5,"author":6,"body":9,"date":5058,"description":5059,"draft":5060,"extension":5061,"howTo":5062,"image":5086,"meta":5087,"navigation":516,"path":5088,"seo":5089,"stem":5090,"tags":5091,"updated":5086,"__hash__":5095},"blogEs/es/blog/001.gofpdf-migration.md","gofpdf está archivado. Guía para migrar a gpdf.",{"name":7,"url":8},"gpdf team","https://gpdf.dev",{"type":10,"value":11,"toc":5042},"minimark",[12,17,38,49,52,66,69,73,79,86,93,100,104,113,141,147,151,154,434,447,477,481,484,489,720,725,1189,1199,1213,1217,1227,1231,1984,1987,1991,2372,2389,2392,2396,2402,2406,2569,2578,2582,3035,3038,3049,3052,3055,3059,3078,3082,3404,3410,3414,4090,4105,4109,4123,4127,4405,4409,4729,4745,4749,4759,4855,4858,4861,4865,4868,4909,4912,4916,4922,4944,4954,4966,4972,4976,4979,4996,5011,5015,5038],[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"," es una biblioteca Go pura, sin dependencias externas, con soporte CJK nativo (nada del baile de ",[26,27,28],"code",{},"AddUTF8Font","), que usa una cuadrícula de 12 columnas en lugar de empujar píxeles con ",[26,31,32],{},"SetXY"," y corre aproximadamente ",[21,35,36],{},"10× más rápido que gofpdf"," en las mismas cargas. La migración consiste básicamente en reemplazar llamadas imperativas al cursor por constructores declarativos. Esta guía recorre el mapeo con cinco pares antes/después.",[18,39,40,41,44,45,48],{},"La semana pasada un compañero abrió un proyecto Go nuevo, ejecutó ",[26,42,43],{},"go get github.com/jung-kurt/gofpdf"," y a los diez minutos me mandó una captura del banner de GitHub: ",[21,46,47],{},"\"This repository has been archived by the owner. It is now read-only.\""," Seguido de: \"Espera, ¿el fork también está archivado?\"",[18,50,51],{},"Sí. Los dos.",[18,53,54,57,58,61,62,65],{},[26,55,56],{},"jung-kurt/gofpdf"," fue archivado el ",[21,59,60],{},"8 de septiembre de 2021",". El fork comunitario ",[26,63,64],{},"go-pdf/fpdf"," publicó su última versión en 2023 y fue archivado en 2025. La biblioteca Go que dos tercios de las respuestas de Stack Overflow todavía recomiendan lleva cuatro años en solo lectura, y el fork que se suponía que la reemplazaba ya no está.",[18,67,68],{},"Si tienes código gofpdf en producción, este post es un mapa de migración. Si estás empezando un proyecto nuevo y fuiste a por gofpdf por reflejo, porque eso es lo que devolvía el buscador, esta es la alternativa.",[13,70,72],{"id":71},"por-qué-gofpdf-no-vuelve","Por qué gofpdf no vuelve",[18,74,75,76,78],{},"Las bibliotecas open source no siempre mueren. A veces el mantenedor original se retira y otra persona toma el relevo. Eso es lo que casi todos asumían que pasaría con gofpdf — y durante un tiempo pasó. El fork ",[26,77,64],{}," reorganizó el código, arregló algunos bugs viejos, aceptó PRs y parecía una continuación legítima.",[18,80,81,82],{},"Entonces, a principios de 2025, el fork también fue archivado. El README dice ahora, en parte: ",[83,84,85],"em",{},"\"Este proyecto ya no se mantiene activamente. Considera usar otra biblioteca.\"",[18,87,88,89,92],{},"La razón importa menos que la consecuencia: ",[21,90,91],{},"todo proyecto Go que depende de gofpdf está ahora sobre dos capas de código sin mantenimiento",". Los problemas de seguridad no se parchean. La especificación PDF 2.0 salió en 2020 y gofpdf no cubre la mayoría de sus cambios. La semántica de variables de bucle de Go 1.25 funciona con gofpdf hoy, pero lo que se rompa mañana lo arreglas tú en tu fork privado.",[18,94,95,96,99],{},"No es un problema de \"la biblioteca tiene bugs\". Es un problema de ",[21,97,98],{},"cadena de suministro",".",[13,101,103],{"id":102},"para-qué-usa-realmente-la-gente-gofpdf","Para qué usa realmente la gente gofpdf",[18,105,106,107,109,110,112],{},"Antes de entrar en el mapeo, ayuda ser específico sobre las cargas que se migran. Mirando los rastreadores de issues y las preguntas de Stack Overflow sobre ",[26,108,56],{}," y ",[26,111,64],{},", los usos dominantes son:",[114,115,116,123,129,135],"ol",{},[117,118,119,122],"li",{},[21,120,121],{},"Facturas y recibos"," — cabecera, bloque de cliente, tabla de líneas, totales, pie.",[117,124,125,128],{},[21,126,127],{},"Informes"," — documentos multipágina con cabeceras repetidas, números de página, gráficos insertados como imágenes.",[117,130,131,134],{},[21,132,133],{},"Formularios y certificados"," — texto en posiciones fijas superpuesto sobre una plantilla.",[117,136,137,140],{},[21,138,139],{},"Documentos CJK"," — facturas y etiquetas de envío en japonés, chino, coreano.",[18,142,143,144,146],{},"Los tres primeros los cubre sin problema la API de builder de gpdf. El cuarto — CJK — es donde gpdf más separa a gofpdf: gofpdf te obligaba a llamar ",[26,145,28],{},", a gestionar una ruta a un TTF y a rezar para que tu texto no saliera del plano básico. gpdf trata CJK como ciudadano de primera clase: registras una fuente TrueType, escribes en japonés, obtienes un PDF.",[13,148,150],{"id":149},"la-tabla-de-mapeo-de-api","La tabla de mapeo de API",[18,152,153],{},"La siguiente tabla es la chuleta. Las secciones de después recorren cinco pares antes/después concretos.",[155,156,157,172],"table",{},[158,159,160],"thead",{},[161,162,163,167,170],"tr",{},[164,165,166],"th",{},"Lo que quieres hacer",[164,168,169],{},"gofpdf",[164,171,23],{},[173,174,175,191,214,237,255,270,288,306,321,336,354,369,384,404,419],"tbody",{},[161,176,177,181,186],{},[178,179,180],"td",{},"Crear un documento",[178,182,183],{},[26,184,185],{},"gofpdf.New(\"P\", \"mm\", \"A4\", \"\")",[178,187,188],{},[26,189,190],{},"gpdf.NewDocument(gpdf.WithPageSize(document.A4))",[161,192,193,196,201],{},[178,194,195],{},"Añadir una página",[178,197,198],{},[26,199,200],{},"pdf.AddPage()",[178,202,203,206,207],{},[26,204,205],{},"doc.AddPage()"," ",[83,208,209,210,213],{},"(devuelve un ",[26,211,212],{},"*PageBuilder",")",[161,215,216,219,224],{},[178,217,218],{},"Fijar una fuente",[178,220,221],{},[26,222,223],{},"pdf.SetFont(\"Arial\", \"B\", 16)",[178,225,226,229,230,229,233,236],{},[26,227,228],{},"template.FontFamily(...)",", ",[26,231,232],{},"template.Bold()",[26,234,235],{},"template.FontSize(16)"," como opciones de texto",[161,238,239,242,247],{},[178,240,241],{},"Registrar un TTF (CJK)",[178,243,244],{},[26,245,246],{},"pdf.AddUTF8Font(\"noto\", \"\", \"NotoSansJP-Regular.ttf\")",[178,248,249,206,252],{},[26,250,251],{},"gpdf.WithFont(\"NotoSansJP\", ttfBytes)",[83,253,254],{},"(al construir)",[161,256,257,260,265],{},[178,258,259],{},"Escribir una línea",[178,261,262],{},[26,263,264],{},"pdf.Cell(40, 10, \"hi\")",[178,266,267],{},[26,268,269],{},"c.Text(\"hi\")",[161,271,272,275,280],{},[178,273,274],{},"Escribir texto con salto",[178,276,277],{},[26,278,279],{},"pdf.MultiCell(0, 10, body, \"\", \"L\", false)",[178,281,282,206,285],{},[26,283,284],{},"c.Text(body)",[83,286,287],{},"(hace el salto automáticamente)",[161,289,290,293,298],{},[178,291,292],{},"Color del texto",[178,294,295],{},[26,296,297],{},"pdf.SetTextColor(255, 0, 0)",[178,299,300,206,303],{},[26,301,302],{},"template.TextColor(pdf.Red)",[83,304,305],{},"(opción por texto)",[161,307,308,311,316],{},[178,309,310],{},"Dibujar una línea horizontal",[178,312,313],{},[26,314,315],{},"pdf.Line(x1, y1, x2, y2)",[178,317,318],{},[26,319,320],{},"c.Line(template.LineThickness(document.Pt(1)))",[161,322,323,326,331],{},[178,324,325],{},"Insertar una imagen",[178,327,328],{},[26,329,330],{},"pdf.ImageOptions(\"logo.png\", x, y, w, h, ...)",[178,332,333],{},[26,334,335],{},"c.Image(imgBytes, template.FitWidth(document.Mm(50)))",[161,337,338,341,346],{},[178,339,340],{},"Fijar cursor XY",[178,342,343],{},[26,344,345],{},"pdf.SetXY(x, y)",[178,347,348],{},[83,349,350,351,213],{},"(no existe equivalente — usa filas/columnas o ",[26,352,353],{},"page.Absolute(x, y, fn)",[161,355,356,359,364],{},[178,357,358],{},"Cabecera repetida",[178,360,361],{},[26,362,363],{},"pdf.SetHeaderFunc(fn)",[178,365,366],{},[26,367,368],{},"doc.Header(fn)",[161,370,371,374,379],{},[178,372,373],{},"Pie repetido",[178,375,376],{},[26,377,378],{},"pdf.SetFooterFunc(fn)",[178,380,381],{},[26,382,383],{},"doc.Footer(fn)",[161,385,386,389,395],{},[178,387,388],{},"Número de página",[178,390,391,392],{},"manual: ",[26,393,394],{},"pdf.PageNo()",[178,396,397,400,401],{},[26,398,399],{},"c.PageNumber()"," / ",[26,402,403],{},"c.TotalPages()",[161,405,406,409,414],{},[178,407,408],{},"Salida a archivo",[178,410,411],{},[26,412,413],{},"pdf.OutputFileAndClose(\"out.pdf\")",[178,415,416],{},[26,417,418],{},"data, _ := doc.Generate(); os.WriteFile(\"out.pdf\", data, 0o644)",[161,420,421,424,429],{},[178,422,423],{},"Salida a writer",[178,425,426],{},[26,427,428],{},"pdf.Output(w)",[178,430,431],{},[26,432,433],{},"doc.Render(w)",[18,435,436,437,440,441,444,445,99],{},"El cambio de forma es lo más fuerte: gofpdf es ",[21,438,439],{},"imperativo",", gpdf es ",[21,442,443],{},"declarativo",". En gofpdf empujas un cursor por la página y escribes donde cae. En gpdf describes un árbol de filas y columnas y dejas que el motor de layout coloque las cosas. Los primeros fragmentos parecen más largos en gpdf. Para el tercero dejas de echar de menos ",[26,446,32],{},[18,448,449,450,229,453,229,456,459,460,229,463,229,466,229,469,472,473,476],{},"Una nota sobre unidades. gofpdf te hace elegir una unidad base al construir (",[26,451,452],{},"\"mm\"",[26,454,455],{},"\"pt\"",[26,457,458],{},"\"in\"","). gpdf usa puntos internamente y te da helpers — ",[26,461,462],{},"document.Mm(20)",[26,464,465],{},"document.Pt(12)",[26,467,468],{},"document.Cm(1)",[26,470,471],{},"document.In(0.5)"," — para la unidad que prefieras en el punto de llamada. Es más parecido a CSS que a gofpdf, y una vez que pones una cabecera en cada página con márgenes de ",[26,474,475],{},"document.Mm(15)",", dejas de pensar en la unidad.",[13,478,480],{"id":479},"antes-después-1-el-pdf-más-simple-posible","Antes / Después 1: el PDF más simple posible",[18,482,483],{},"El par \"hello world\". La brevedad de gofpdf es lo que lo hizo tan citable. La versión gpdf tiene unas líneas más porque construye un árbol, no conduce un cursor.",[18,485,486],{},[21,487,488],{},"Antes — gofpdf:",[490,491,496],"pre",{"className":492,"code":493,"language":494,"meta":495,"style":495},"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,497,498,511,518,534,539,555,612,626,662,693,714],{"__ignoreMap":495},[499,500,503,507],"span",{"class":501,"line":502},"line",1,[499,504,506],{"class":505},"sMK4o","package",[499,508,510],{"class":509},"sBMFI"," main\n",[499,512,514],{"class":501,"line":513},2,[499,515,517],{"emptyLinePlaceholder":516},true,"\n",[499,519,521,525,528,531],{"class":501,"line":520},3,[499,522,524],{"class":523},"s7zQu","import",[499,526,527],{"class":505}," \"",[499,529,530],{"class":509},"github.com/jung-kurt/gofpdf",[499,532,533],{"class":505},"\"\n",[499,535,537],{"class":501,"line":536},4,[499,538,517],{"emptyLinePlaceholder":516},[499,540,542,545,549,552],{"class":501,"line":541},5,[499,543,544],{"class":505},"func",[499,546,548],{"class":547},"s2Zo4"," main",[499,550,551],{"class":505},"()",[499,553,554],{"class":505}," {\n",[499,556,558,562,565,568,570,573,576,579,583,585,588,590,593,595,597,599,602,604,606,609],{"class":501,"line":557},6,[499,559,561],{"class":560},"sTEyZ","    pdf ",[499,563,564],{"class":505},":=",[499,566,567],{"class":560}," gofpdf",[499,569,99],{"class":505},[499,571,572],{"class":547},"New",[499,574,575],{"class":505},"(",[499,577,578],{"class":505},"\"",[499,580,582],{"class":581},"sfazB","P",[499,584,578],{"class":505},[499,586,587],{"class":505},",",[499,589,527],{"class":505},[499,591,592],{"class":581},"mm",[499,594,578],{"class":505},[499,596,587],{"class":505},[499,598,527],{"class":505},[499,600,601],{"class":581},"A4",[499,603,578],{"class":505},[499,605,587],{"class":505},[499,607,608],{"class":505}," \"\"",[499,610,611],{"class":505},")\n",[499,613,615,618,620,623],{"class":501,"line":614},7,[499,616,617],{"class":560},"    pdf",[499,619,99],{"class":505},[499,621,622],{"class":547},"AddPage",[499,624,625],{"class":505},"()\n",[499,627,629,631,633,636,638,640,643,645,647,649,652,654,656,660],{"class":501,"line":628},8,[499,630,617],{"class":560},[499,632,99],{"class":505},[499,634,635],{"class":547},"SetFont",[499,637,575],{"class":505},[499,639,578],{"class":505},[499,641,642],{"class":581},"Arial",[499,644,578],{"class":505},[499,646,587],{"class":505},[499,648,527],{"class":505},[499,650,651],{"class":581},"B",[499,653,578],{"class":505},[499,655,587],{"class":505},[499,657,659],{"class":658},"sbssI"," 24",[499,661,611],{"class":505},[499,663,665,667,669,672,674,677,679,682,684,686,689,691],{"class":501,"line":664},9,[499,666,617],{"class":560},[499,668,99],{"class":505},[499,670,671],{"class":547},"Cell",[499,673,575],{"class":505},[499,675,676],{"class":658},"40",[499,678,587],{"class":505},[499,680,681],{"class":658}," 10",[499,683,587],{"class":505},[499,685,527],{"class":505},[499,687,688],{"class":581},"Hello, World!",[499,690,578],{"class":505},[499,692,611],{"class":505},[499,694,696,698,700,703,705,707,710,712],{"class":501,"line":695},10,[499,697,617],{"class":560},[499,699,99],{"class":505},[499,701,702],{"class":547},"OutputFileAndClose",[499,704,575],{"class":505},[499,706,578],{"class":505},[499,708,709],{"class":581},"hello.pdf",[499,711,578],{"class":505},[499,713,611],{"class":505},[499,715,717],{"class":501,"line":716},11,[499,718,719],{"class":505},"}\n",[18,721,722],{},[21,723,724],{},"Después — gpdf:",[490,726,728],{"className":492,"code":727,"language":494,"meta":495,"style":495},"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,729,730,736,740,747,757,766,770,779,788,797,801,805,816,835,858,894,900,905,922,955,992,1039,1045,1051,1056,1078,1094,1112,1118,1164,1179,1184],{"__ignoreMap":495},[499,731,732,734],{"class":501,"line":502},[499,733,506],{"class":505},[499,735,510],{"class":509},[499,737,738],{"class":501,"line":513},[499,739,517],{"emptyLinePlaceholder":516},[499,741,742,744],{"class":501,"line":520},[499,743,524],{"class":523},[499,745,746],{"class":505}," (\n",[499,748,749,752,755],{"class":501,"line":536},[499,750,751],{"class":505},"    \"",[499,753,754],{"class":509},"log",[499,756,533],{"class":505},[499,758,759,761,764],{"class":501,"line":541},[499,760,751],{"class":505},[499,762,763],{"class":509},"os",[499,765,533],{"class":505},[499,767,768],{"class":501,"line":557},[499,769,517],{"emptyLinePlaceholder":516},[499,771,772,774,777],{"class":501,"line":614},[499,773,751],{"class":505},[499,775,776],{"class":509},"github.com/gpdf-dev/gpdf",[499,778,533],{"class":505},[499,780,781,783,786],{"class":501,"line":628},[499,782,751],{"class":505},[499,784,785],{"class":509},"github.com/gpdf-dev/gpdf/document",[499,787,533],{"class":505},[499,789,790,792,795],{"class":501,"line":664},[499,791,751],{"class":505},[499,793,794],{"class":509},"github.com/gpdf-dev/gpdf/template",[499,796,533],{"class":505},[499,798,799],{"class":501,"line":695},[499,800,611],{"class":505},[499,802,803],{"class":501,"line":716},[499,804,517],{"emptyLinePlaceholder":516},[499,806,808,810,812,814],{"class":501,"line":807},12,[499,809,544],{"class":505},[499,811,548],{"class":547},[499,813,551],{"class":505},[499,815,554],{"class":505},[499,817,819,822,824,827,829,832],{"class":501,"line":818},13,[499,820,821],{"class":560},"    doc ",[499,823,564],{"class":505},[499,825,826],{"class":560}," gpdf",[499,828,99],{"class":505},[499,830,831],{"class":547},"NewDocument",[499,833,834],{"class":505},"(\n",[499,836,838,841,843,846,848,851,853,855],{"class":501,"line":837},14,[499,839,840],{"class":560},"        gpdf",[499,842,99],{"class":505},[499,844,845],{"class":547},"WithPageSize",[499,847,575],{"class":505},[499,849,850],{"class":560},"document",[499,852,99],{"class":505},[499,854,601],{"class":560},[499,856,857],{"class":505},"),\n",[499,859,861,863,865,868,870,872,874,877,879,881,883,886,888,891],{"class":501,"line":860},15,[499,862,840],{"class":560},[499,864,99],{"class":505},[499,866,867],{"class":547},"WithMargins",[499,869,575],{"class":505},[499,871,850],{"class":560},[499,873,99],{"class":505},[499,875,876],{"class":547},"UniformEdges",[499,878,575],{"class":505},[499,880,850],{"class":560},[499,882,99],{"class":505},[499,884,885],{"class":547},"Mm",[499,887,575],{"class":505},[499,889,890],{"class":658},"20",[499,892,893],{"class":505},"))),\n",[499,895,897],{"class":501,"line":896},16,[499,898,899],{"class":505},"    )\n",[499,901,903],{"class":501,"line":902},17,[499,904,517],{"emptyLinePlaceholder":516},[499,906,908,911,913,916,918,920],{"class":501,"line":907},18,[499,909,910],{"class":560},"    page ",[499,912,564],{"class":505},[499,914,915],{"class":560}," doc",[499,917,99],{"class":505},[499,919,622],{"class":547},[499,921,625],{"class":505},[499,923,925,928,930,933,936,940,943,946,948,951,953],{"class":501,"line":924},19,[499,926,927],{"class":560},"    page",[499,929,99],{"class":505},[499,931,932],{"class":547},"AutoRow",[499,934,935],{"class":505},"(func(",[499,937,939],{"class":938},"sHdIc","r",[499,941,942],{"class":505}," *",[499,944,945],{"class":509},"template",[499,947,99],{"class":505},[499,949,950],{"class":509},"RowBuilder",[499,952,213],{"class":505},[499,954,554],{"class":505},[499,956,958,961,963,966,968,971,973,976,979,981,983,985,988,990],{"class":501,"line":957},20,[499,959,960],{"class":560},"        r",[499,962,99],{"class":505},[499,964,965],{"class":547},"Col",[499,967,575],{"class":505},[499,969,970],{"class":658},"12",[499,972,587],{"class":505},[499,974,975],{"class":505}," func(",[499,977,978],{"class":938},"c",[499,980,942],{"class":505},[499,982,945],{"class":509},[499,984,99],{"class":505},[499,986,987],{"class":509},"ColBuilder",[499,989,213],{"class":505},[499,991,554],{"class":505},[499,993,995,998,1000,1003,1005,1007,1009,1011,1013,1016,1018,1021,1023,1026,1029,1031,1033,1036],{"class":501,"line":994},21,[499,996,997],{"class":560},"            c",[499,999,99],{"class":505},[499,1001,1002],{"class":547},"Text",[499,1004,575],{"class":505},[499,1006,578],{"class":505},[499,1008,688],{"class":581},[499,1010,578],{"class":505},[499,1012,587],{"class":505},[499,1014,1015],{"class":560}," template",[499,1017,99],{"class":505},[499,1019,1020],{"class":547},"FontSize",[499,1022,575],{"class":505},[499,1024,1025],{"class":658},"24",[499,1027,1028],{"class":505},"),",[499,1030,1015],{"class":560},[499,1032,99],{"class":505},[499,1034,1035],{"class":547},"Bold",[499,1037,1038],{"class":505},"())\n",[499,1040,1042],{"class":501,"line":1041},22,[499,1043,1044],{"class":505},"        })\n",[499,1046,1048],{"class":501,"line":1047},23,[499,1049,1050],{"class":505},"    })\n",[499,1052,1054],{"class":501,"line":1053},24,[499,1055,517],{"emptyLinePlaceholder":516},[499,1057,1059,1062,1064,1067,1069,1071,1073,1076],{"class":501,"line":1058},25,[499,1060,1061],{"class":560},"    data",[499,1063,587],{"class":505},[499,1065,1066],{"class":560}," err ",[499,1068,564],{"class":505},[499,1070,915],{"class":560},[499,1072,99],{"class":505},[499,1074,1075],{"class":547},"Generate",[499,1077,625],{"class":505},[499,1079,1081,1084,1086,1089,1092],{"class":501,"line":1080},26,[499,1082,1083],{"class":523},"    if",[499,1085,1066],{"class":560},[499,1087,1088],{"class":505},"!=",[499,1090,1091],{"class":505}," nil",[499,1093,554],{"class":505},[499,1095,1097,1100,1102,1105,1107,1110],{"class":501,"line":1096},27,[499,1098,1099],{"class":560},"        log",[499,1101,99],{"class":505},[499,1103,1104],{"class":547},"Fatal",[499,1106,575],{"class":505},[499,1108,1109],{"class":560},"err",[499,1111,611],{"class":505},[499,1113,1115],{"class":501,"line":1114},28,[499,1116,1117],{"class":505},"    }\n",[499,1119,1121,1123,1125,1127,1130,1132,1135,1137,1139,1141,1143,1145,1148,1150,1153,1156,1158,1160,1162],{"class":501,"line":1120},29,[499,1122,1083],{"class":523},[499,1124,1066],{"class":560},[499,1126,564],{"class":505},[499,1128,1129],{"class":560}," os",[499,1131,99],{"class":505},[499,1133,1134],{"class":547},"WriteFile",[499,1136,575],{"class":505},[499,1138,578],{"class":505},[499,1140,709],{"class":581},[499,1142,578],{"class":505},[499,1144,587],{"class":505},[499,1146,1147],{"class":560}," data",[499,1149,587],{"class":505},[499,1151,1152],{"class":658}," 0o644",[499,1154,1155],{"class":505},");",[499,1157,1066],{"class":560},[499,1159,1088],{"class":505},[499,1161,1091],{"class":505},[499,1163,554],{"class":505},[499,1165,1167,1169,1171,1173,1175,1177],{"class":501,"line":1166},30,[499,1168,1099],{"class":560},[499,1170,99],{"class":505},[499,1172,1104],{"class":547},[499,1174,575],{"class":505},[499,1176,1109],{"class":560},[499,1178,611],{"class":505},[499,1180,1182],{"class":501,"line":1181},31,[499,1183,1117],{"class":505},[499,1185,1187],{"class":501,"line":1186},32,[499,1188,719],{"class":505},[18,1190,1191,1192,1194,1195,1198],{},"La cuadrícula hace el trabajo. ",[26,1193,932],{}," añade una fila cuya altura viene de su contenido; ",[26,1196,1197],{},"r.Col(12, ...)"," dice \"esta columna ocupa las 12 columnas de la cuadrícula\". La misma idea de Bootstrap, aplicada a una página PDF.",[18,1200,1201,1204,1205,1208,1209,1212],{},[26,1202,1203],{},"Generate()"," devuelve los bytes; ",[26,1206,1207],{},"Render(w)"," los transmite a un ",[26,1210,1211],{},"io.Writer"," si prefieres no asignar. No hay paso de \"cerrar el archivo\" porque gpdf no es dueño de ningún file handle.",[13,1214,1216],{"id":1215},"antes-después-2-una-tabla-de-líneas-de-factura","Antes / Después 2: una tabla de líneas de factura",[18,1218,1219,1220,1222,1223,1226],{},"Donde gofpdf se vuelve verboso es en las tablas. No tiene tabla integrada; llamas a ",[26,1221,671],{}," en bucles anidados, gestionas el ancho de columnas a mano y haces ",[26,1224,1225],{},"Ln(-1)"," para ir a la siguiente fila. La mitad de los tutoriales de facturas con gofpdf en internet son, literalmente, plantilla de tabla.",[18,1228,1229],{},[21,1230,488],{},[490,1232,1234],{"className":492,"code":1233,"language":494,"meta":495,"style":495},"pdf.SetFont(\"Arial\", \"B\", 11)\npdf.SetFillColor(220, 220, 220)\npdf.CellFormat(80, 8, \"Descripción\", \"1\", 0, \"L\", true, 0, \"\")\npdf.CellFormat(20, 8, \"Uds.\",        \"1\", 0, \"C\", true, 0, \"\")\npdf.CellFormat(30, 8, \"Precio\",      \"1\", 0, \"R\", true, 0, \"\")\npdf.CellFormat(30, 8, \"Importe\",     \"1\", 1, \"R\", true, 0, \"\")\n\npdf.SetFont(\"Arial\", \"\", 11)\nitems := [][]string{\n    {\"Desarrollo frontend\", \"40 h\", \"150,00 €\", \"6.000,00 €\"},\n    {\"Desarrollo backend\",  \"60 h\", \"150,00 €\", \"9.000,00 €\"},\n    {\"Diseño UI\",           \"20 h\", \"120,00 €\", \"2.400,00 €\"},\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,1235,1236,1268,1293,1360,1421,1483,1544,1548,1574,1591,1633,1673,1714,1718,1741,1804,1862,1921,1980],{"__ignoreMap":495},[499,1237,1238,1241,1243,1245,1247,1249,1251,1253,1255,1257,1259,1261,1263,1266],{"class":501,"line":502},[499,1239,1240],{"class":560},"pdf",[499,1242,99],{"class":505},[499,1244,635],{"class":547},[499,1246,575],{"class":505},[499,1248,578],{"class":505},[499,1250,642],{"class":581},[499,1252,578],{"class":505},[499,1254,587],{"class":505},[499,1256,527],{"class":505},[499,1258,651],{"class":581},[499,1260,578],{"class":505},[499,1262,587],{"class":505},[499,1264,1265],{"class":658}," 11",[499,1267,611],{"class":505},[499,1269,1270,1272,1274,1277,1279,1282,1284,1287,1289,1291],{"class":501,"line":513},[499,1271,1240],{"class":560},[499,1273,99],{"class":505},[499,1275,1276],{"class":547},"SetFillColor",[499,1278,575],{"class":505},[499,1280,1281],{"class":658},"220",[499,1283,587],{"class":505},[499,1285,1286],{"class":658}," 220",[499,1288,587],{"class":505},[499,1290,1286],{"class":658},[499,1292,611],{"class":505},[499,1294,1295,1297,1299,1302,1304,1307,1309,1312,1314,1316,1319,1321,1323,1325,1328,1330,1332,1335,1337,1339,1342,1344,1346,1350,1352,1354,1356,1358],{"class":501,"line":520},[499,1296,1240],{"class":560},[499,1298,99],{"class":505},[499,1300,1301],{"class":547},"CellFormat",[499,1303,575],{"class":505},[499,1305,1306],{"class":658},"80",[499,1308,587],{"class":505},[499,1310,1311],{"class":658}," 8",[499,1313,587],{"class":505},[499,1315,527],{"class":505},[499,1317,1318],{"class":581},"Descripción",[499,1320,578],{"class":505},[499,1322,587],{"class":505},[499,1324,527],{"class":505},[499,1326,1327],{"class":581},"1",[499,1329,578],{"class":505},[499,1331,587],{"class":505},[499,1333,1334],{"class":658}," 0",[499,1336,587],{"class":505},[499,1338,527],{"class":505},[499,1340,1341],{"class":581},"L",[499,1343,578],{"class":505},[499,1345,587],{"class":505},[499,1347,1349],{"class":1348},"sfNiH"," true",[499,1351,587],{"class":505},[499,1353,1334],{"class":658},[499,1355,587],{"class":505},[499,1357,608],{"class":505},[499,1359,611],{"class":505},[499,1361,1362,1364,1366,1368,1370,1372,1374,1376,1378,1380,1383,1385,1387,1390,1392,1394,1396,1398,1400,1402,1405,1407,1409,1411,1413,1415,1417,1419],{"class":501,"line":536},[499,1363,1240],{"class":560},[499,1365,99],{"class":505},[499,1367,1301],{"class":547},[499,1369,575],{"class":505},[499,1371,890],{"class":658},[499,1373,587],{"class":505},[499,1375,1311],{"class":658},[499,1377,587],{"class":505},[499,1379,527],{"class":505},[499,1381,1382],{"class":581},"Uds.",[499,1384,578],{"class":505},[499,1386,587],{"class":505},[499,1388,1389],{"class":505},"        \"",[499,1391,1327],{"class":581},[499,1393,578],{"class":505},[499,1395,587],{"class":505},[499,1397,1334],{"class":658},[499,1399,587],{"class":505},[499,1401,527],{"class":505},[499,1403,1404],{"class":581},"C",[499,1406,578],{"class":505},[499,1408,587],{"class":505},[499,1410,1349],{"class":1348},[499,1412,587],{"class":505},[499,1414,1334],{"class":658},[499,1416,587],{"class":505},[499,1418,608],{"class":505},[499,1420,611],{"class":505},[499,1422,1423,1425,1427,1429,1431,1434,1436,1438,1440,1442,1445,1447,1449,1452,1454,1456,1458,1460,1462,1464,1467,1469,1471,1473,1475,1477,1479,1481],{"class":501,"line":541},[499,1424,1240],{"class":560},[499,1426,99],{"class":505},[499,1428,1301],{"class":547},[499,1430,575],{"class":505},[499,1432,1433],{"class":658},"30",[499,1435,587],{"class":505},[499,1437,1311],{"class":658},[499,1439,587],{"class":505},[499,1441,527],{"class":505},[499,1443,1444],{"class":581},"Precio",[499,1446,578],{"class":505},[499,1448,587],{"class":505},[499,1450,1451],{"class":505},"      \"",[499,1453,1327],{"class":581},[499,1455,578],{"class":505},[499,1457,587],{"class":505},[499,1459,1334],{"class":658},[499,1461,587],{"class":505},[499,1463,527],{"class":505},[499,1465,1466],{"class":581},"R",[499,1468,578],{"class":505},[499,1470,587],{"class":505},[499,1472,1349],{"class":1348},[499,1474,587],{"class":505},[499,1476,1334],{"class":658},[499,1478,587],{"class":505},[499,1480,608],{"class":505},[499,1482,611],{"class":505},[499,1484,1485,1487,1489,1491,1493,1495,1497,1499,1501,1503,1506,1508,1510,1513,1515,1517,1519,1522,1524,1526,1528,1530,1532,1534,1536,1538,1540,1542],{"class":501,"line":557},[499,1486,1240],{"class":560},[499,1488,99],{"class":505},[499,1490,1301],{"class":547},[499,1492,575],{"class":505},[499,1494,1433],{"class":658},[499,1496,587],{"class":505},[499,1498,1311],{"class":658},[499,1500,587],{"class":505},[499,1502,527],{"class":505},[499,1504,1505],{"class":581},"Importe",[499,1507,578],{"class":505},[499,1509,587],{"class":505},[499,1511,1512],{"class":505},"     \"",[499,1514,1327],{"class":581},[499,1516,578],{"class":505},[499,1518,587],{"class":505},[499,1520,1521],{"class":658}," 1",[499,1523,587],{"class":505},[499,1525,527],{"class":505},[499,1527,1466],{"class":581},[499,1529,578],{"class":505},[499,1531,587],{"class":505},[499,1533,1349],{"class":1348},[499,1535,587],{"class":505},[499,1537,1334],{"class":658},[499,1539,587],{"class":505},[499,1541,608],{"class":505},[499,1543,611],{"class":505},[499,1545,1546],{"class":501,"line":614},[499,1547,517],{"emptyLinePlaceholder":516},[499,1549,1550,1552,1554,1556,1558,1560,1562,1564,1566,1568,1570,1572],{"class":501,"line":628},[499,1551,1240],{"class":560},[499,1553,99],{"class":505},[499,1555,635],{"class":547},[499,1557,575],{"class":505},[499,1559,578],{"class":505},[499,1561,642],{"class":581},[499,1563,578],{"class":505},[499,1565,587],{"class":505},[499,1567,608],{"class":505},[499,1569,587],{"class":505},[499,1571,1265],{"class":658},[499,1573,611],{"class":505},[499,1575,1576,1579,1581,1584,1588],{"class":501,"line":664},[499,1577,1578],{"class":560},"items ",[499,1580,564],{"class":505},[499,1582,1583],{"class":505}," [][]",[499,1585,1587],{"class":1586},"spNyl","string",[499,1589,1590],{"class":505},"{\n",[499,1592,1593,1596,1598,1601,1603,1605,1607,1610,1612,1614,1616,1619,1621,1623,1625,1628,1630],{"class":501,"line":695},[499,1594,1595],{"class":505},"    {",[499,1597,578],{"class":505},[499,1599,1600],{"class":581},"Desarrollo frontend",[499,1602,578],{"class":505},[499,1604,587],{"class":505},[499,1606,527],{"class":505},[499,1608,1609],{"class":581},"40 h",[499,1611,578],{"class":505},[499,1613,587],{"class":505},[499,1615,527],{"class":505},[499,1617,1618],{"class":581},"150,00 €",[499,1620,578],{"class":505},[499,1622,587],{"class":505},[499,1624,527],{"class":505},[499,1626,1627],{"class":581},"6.000,00 €",[499,1629,578],{"class":505},[499,1631,1632],{"class":505},"},\n",[499,1634,1635,1637,1639,1642,1644,1646,1649,1652,1654,1656,1658,1660,1662,1664,1666,1669,1671],{"class":501,"line":716},[499,1636,1595],{"class":505},[499,1638,578],{"class":505},[499,1640,1641],{"class":581},"Desarrollo backend",[499,1643,578],{"class":505},[499,1645,587],{"class":505},[499,1647,1648],{"class":505},"  \"",[499,1650,1651],{"class":581},"60 h",[499,1653,578],{"class":505},[499,1655,587],{"class":505},[499,1657,527],{"class":505},[499,1659,1618],{"class":581},[499,1661,578],{"class":505},[499,1663,587],{"class":505},[499,1665,527],{"class":505},[499,1667,1668],{"class":581},"9.000,00 €",[499,1670,578],{"class":505},[499,1672,1632],{"class":505},[499,1674,1675,1677,1679,1682,1684,1686,1689,1692,1694,1696,1698,1701,1703,1705,1707,1710,1712],{"class":501,"line":807},[499,1676,1595],{"class":505},[499,1678,578],{"class":505},[499,1680,1681],{"class":581},"Diseño UI",[499,1683,578],{"class":505},[499,1685,587],{"class":505},[499,1687,1688],{"class":505},"           \"",[499,1690,1691],{"class":581},"20 h",[499,1693,578],{"class":505},[499,1695,587],{"class":505},[499,1697,527],{"class":505},[499,1699,1700],{"class":581},"120,00 €",[499,1702,578],{"class":505},[499,1704,587],{"class":505},[499,1706,527],{"class":505},[499,1708,1709],{"class":581},"2.400,00 €",[499,1711,578],{"class":505},[499,1713,1632],{"class":505},[499,1715,1716],{"class":501,"line":818},[499,1717,719],{"class":505},[499,1719,1720,1723,1726,1728,1731,1733,1736,1739],{"class":501,"line":837},[499,1721,1722],{"class":523},"for",[499,1724,1725],{"class":560}," _",[499,1727,587],{"class":505},[499,1729,1730],{"class":560}," row ",[499,1732,564],{"class":505},[499,1734,1735],{"class":523}," range",[499,1737,1738],{"class":560}," items ",[499,1740,1590],{"class":505},[499,1742,1743,1745,1747,1749,1751,1753,1755,1757,1759,1762,1765,1768,1771,1773,1775,1777,1779,1781,1783,1785,1787,1789,1791,1794,1796,1798,1800,1802],{"class":501,"line":860},[499,1744,617],{"class":560},[499,1746,99],{"class":505},[499,1748,1301],{"class":547},[499,1750,575],{"class":505},[499,1752,1306],{"class":658},[499,1754,587],{"class":505},[499,1756,1311],{"class":658},[499,1758,587],{"class":505},[499,1760,1761],{"class":560}," row",[499,1763,1764],{"class":505},"[",[499,1766,1767],{"class":658},"0",[499,1769,1770],{"class":505},"],",[499,1772,527],{"class":505},[499,1774,1327],{"class":581},[499,1776,578],{"class":505},[499,1778,587],{"class":505},[499,1780,1334],{"class":658},[499,1782,587],{"class":505},[499,1784,527],{"class":505},[499,1786,1341],{"class":581},[499,1788,578],{"class":505},[499,1790,587],{"class":505},[499,1792,1793],{"class":1348}," false",[499,1795,587],{"class":505},[499,1797,1334],{"class":658},[499,1799,587],{"class":505},[499,1801,608],{"class":505},[499,1803,611],{"class":505},[499,1805,1806,1808,1810,1812,1814,1816,1818,1820,1822,1824,1826,1828,1830,1832,1834,1836,1838,1840,1842,1844,1846,1848,1850,1852,1854,1856,1858,1860],{"class":501,"line":896},[499,1807,617],{"class":560},[499,1809,99],{"class":505},[499,1811,1301],{"class":547},[499,1813,575],{"class":505},[499,1815,890],{"class":658},[499,1817,587],{"class":505},[499,1819,1311],{"class":658},[499,1821,587],{"class":505},[499,1823,1761],{"class":560},[499,1825,1764],{"class":505},[499,1827,1327],{"class":658},[499,1829,1770],{"class":505},[499,1831,527],{"class":505},[499,1833,1327],{"class":581},[499,1835,578],{"class":505},[499,1837,587],{"class":505},[499,1839,1334],{"class":658},[499,1841,587],{"class":505},[499,1843,527],{"class":505},[499,1845,1404],{"class":581},[499,1847,578],{"class":505},[499,1849,587],{"class":505},[499,1851,1793],{"class":1348},[499,1853,587],{"class":505},[499,1855,1334],{"class":658},[499,1857,587],{"class":505},[499,1859,608],{"class":505},[499,1861,611],{"class":505},[499,1863,1864,1866,1868,1870,1872,1874,1876,1878,1880,1882,1884,1887,1889,1891,1893,1895,1897,1899,1901,1903,1905,1907,1909,1911,1913,1915,1917,1919],{"class":501,"line":902},[499,1865,617],{"class":560},[499,1867,99],{"class":505},[499,1869,1301],{"class":547},[499,1871,575],{"class":505},[499,1873,1433],{"class":658},[499,1875,587],{"class":505},[499,1877,1311],{"class":658},[499,1879,587],{"class":505},[499,1881,1761],{"class":560},[499,1883,1764],{"class":505},[499,1885,1886],{"class":658},"2",[499,1888,1770],{"class":505},[499,1890,527],{"class":505},[499,1892,1327],{"class":581},[499,1894,578],{"class":505},[499,1896,587],{"class":505},[499,1898,1334],{"class":658},[499,1900,587],{"class":505},[499,1902,527],{"class":505},[499,1904,1466],{"class":581},[499,1906,578],{"class":505},[499,1908,587],{"class":505},[499,1910,1793],{"class":1348},[499,1912,587],{"class":505},[499,1914,1334],{"class":658},[499,1916,587],{"class":505},[499,1918,608],{"class":505},[499,1920,611],{"class":505},[499,1922,1923,1925,1927,1929,1931,1933,1935,1937,1939,1941,1943,1946,1948,1950,1952,1954,1956,1958,1960,1962,1964,1966,1968,1970,1972,1974,1976,1978],{"class":501,"line":907},[499,1924,617],{"class":560},[499,1926,99],{"class":505},[499,1928,1301],{"class":547},[499,1930,575],{"class":505},[499,1932,1433],{"class":658},[499,1934,587],{"class":505},[499,1936,1311],{"class":658},[499,1938,587],{"class":505},[499,1940,1761],{"class":560},[499,1942,1764],{"class":505},[499,1944,1945],{"class":658},"3",[499,1947,1770],{"class":505},[499,1949,527],{"class":505},[499,1951,1327],{"class":581},[499,1953,578],{"class":505},[499,1955,587],{"class":505},[499,1957,1521],{"class":658},[499,1959,587],{"class":505},[499,1961,527],{"class":505},[499,1963,1466],{"class":581},[499,1965,578],{"class":505},[499,1967,587],{"class":505},[499,1969,1793],{"class":1348},[499,1971,587],{"class":505},[499,1973,1334],{"class":658},[499,1975,587],{"class":505},[499,1977,608],{"class":505},[499,1979,611],{"class":505},[499,1981,1982],{"class":501,"line":924},[499,1983,719],{"class":505},[18,1985,1986],{},"Calculas anchos mentalmente, y mejor que ninguna descripción tenga que envolver.",[18,1988,1989],{},[21,1990,724],{},[490,1992,1994],{"className":492,"code":1993,"language":494,"meta":495,"style":495},"page.AutoRow(func(r *template.RowBuilder) {\n    r.Col(12, func(c *template.ColBuilder) {\n        c.Table(\n            []string{\"Descripción\", \"Uds.\", \"Precio\", \"Importe\"},\n            [][]string{\n                {\"Desarrollo frontend\", \"40 h\", \"150,00 €\", \"6.000,00 €\"},\n                {\"Desarrollo backend\",  \"60 h\", \"150,00 €\", \"9.000,00 €\"},\n                {\"Diseño UI\",           \"20 h\", \"120,00 €\", \"2.400,00 €\"},\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,1995,1996,2021,2052,2064,2106,2115,2152,2188,2224,2229,2260,2271,2283,2303,2329,2334,2358,2363,2367],{"__ignoreMap":495},[499,1997,1998,2001,2003,2005,2007,2009,2011,2013,2015,2017,2019],{"class":501,"line":502},[499,1999,2000],{"class":560},"page",[499,2002,99],{"class":505},[499,2004,932],{"class":547},[499,2006,935],{"class":505},[499,2008,939],{"class":938},[499,2010,942],{"class":505},[499,2012,945],{"class":509},[499,2014,99],{"class":505},[499,2016,950],{"class":509},[499,2018,213],{"class":505},[499,2020,554],{"class":505},[499,2022,2023,2026,2028,2030,2032,2034,2036,2038,2040,2042,2044,2046,2048,2050],{"class":501,"line":513},[499,2024,2025],{"class":560},"    r",[499,2027,99],{"class":505},[499,2029,965],{"class":547},[499,2031,575],{"class":505},[499,2033,970],{"class":658},[499,2035,587],{"class":505},[499,2037,975],{"class":505},[499,2039,978],{"class":938},[499,2041,942],{"class":505},[499,2043,945],{"class":509},[499,2045,99],{"class":505},[499,2047,987],{"class":509},[499,2049,213],{"class":505},[499,2051,554],{"class":505},[499,2053,2054,2057,2059,2062],{"class":501,"line":520},[499,2055,2056],{"class":560},"        c",[499,2058,99],{"class":505},[499,2060,2061],{"class":547},"Table",[499,2063,834],{"class":505},[499,2065,2066,2069,2071,2074,2076,2078,2080,2082,2084,2086,2088,2090,2092,2094,2096,2098,2100,2102,2104],{"class":501,"line":536},[499,2067,2068],{"class":505},"            []",[499,2070,1587],{"class":1586},[499,2072,2073],{"class":505},"{",[499,2075,578],{"class":505},[499,2077,1318],{"class":581},[499,2079,578],{"class":505},[499,2081,587],{"class":505},[499,2083,527],{"class":505},[499,2085,1382],{"class":581},[499,2087,578],{"class":505},[499,2089,587],{"class":505},[499,2091,527],{"class":505},[499,2093,1444],{"class":581},[499,2095,578],{"class":505},[499,2097,587],{"class":505},[499,2099,527],{"class":505},[499,2101,1505],{"class":581},[499,2103,578],{"class":505},[499,2105,1632],{"class":505},[499,2107,2108,2111,2113],{"class":501,"line":541},[499,2109,2110],{"class":505},"            [][]",[499,2112,1587],{"class":1586},[499,2114,1590],{"class":505},[499,2116,2117,2120,2122,2124,2126,2128,2130,2132,2134,2136,2138,2140,2142,2144,2146,2148,2150],{"class":501,"line":557},[499,2118,2119],{"class":505},"                {",[499,2121,578],{"class":505},[499,2123,1600],{"class":581},[499,2125,578],{"class":505},[499,2127,587],{"class":505},[499,2129,527],{"class":505},[499,2131,1609],{"class":581},[499,2133,578],{"class":505},[499,2135,587],{"class":505},[499,2137,527],{"class":505},[499,2139,1618],{"class":581},[499,2141,578],{"class":505},[499,2143,587],{"class":505},[499,2145,527],{"class":505},[499,2147,1627],{"class":581},[499,2149,578],{"class":505},[499,2151,1632],{"class":505},[499,2153,2154,2156,2158,2160,2162,2164,2166,2168,2170,2172,2174,2176,2178,2180,2182,2184,2186],{"class":501,"line":614},[499,2155,2119],{"class":505},[499,2157,578],{"class":505},[499,2159,1641],{"class":581},[499,2161,578],{"class":505},[499,2163,587],{"class":505},[499,2165,1648],{"class":505},[499,2167,1651],{"class":581},[499,2169,578],{"class":505},[499,2171,587],{"class":505},[499,2173,527],{"class":505},[499,2175,1618],{"class":581},[499,2177,578],{"class":505},[499,2179,587],{"class":505},[499,2181,527],{"class":505},[499,2183,1668],{"class":581},[499,2185,578],{"class":505},[499,2187,1632],{"class":505},[499,2189,2190,2192,2194,2196,2198,2200,2202,2204,2206,2208,2210,2212,2214,2216,2218,2220,2222],{"class":501,"line":628},[499,2191,2119],{"class":505},[499,2193,578],{"class":505},[499,2195,1681],{"class":581},[499,2197,578],{"class":505},[499,2199,587],{"class":505},[499,2201,1688],{"class":505},[499,2203,1691],{"class":581},[499,2205,578],{"class":505},[499,2207,587],{"class":505},[499,2209,527],{"class":505},[499,2211,1700],{"class":581},[499,2213,578],{"class":505},[499,2215,587],{"class":505},[499,2217,527],{"class":505},[499,2219,1709],{"class":581},[499,2221,578],{"class":505},[499,2223,1632],{"class":505},[499,2225,2226],{"class":501,"line":664},[499,2227,2228],{"class":505},"            },\n",[499,2230,2231,2234,2236,2239,2241,2244,2246,2249,2251,2253,2255,2258],{"class":501,"line":695},[499,2232,2233],{"class":560},"            template",[499,2235,99],{"class":505},[499,2237,2238],{"class":547},"ColumnWidths",[499,2240,575],{"class":505},[499,2242,2243],{"class":658},"50",[499,2245,587],{"class":505},[499,2247,2248],{"class":658}," 15",[499,2250,587],{"class":505},[499,2252,2248],{"class":658},[499,2254,587],{"class":505},[499,2256,2257],{"class":658}," 20",[499,2259,857],{"class":505},[499,2261,2262,2264,2266,2269],{"class":501,"line":716},[499,2263,2233],{"class":560},[499,2265,99],{"class":505},[499,2267,2268],{"class":547},"TableHeaderStyle",[499,2270,834],{"class":505},[499,2272,2273,2276,2278,2280],{"class":501,"line":807},[499,2274,2275],{"class":560},"                template",[499,2277,99],{"class":505},[499,2279,1035],{"class":547},[499,2281,2282],{"class":505},"(),\n",[499,2284,2285,2287,2289,2292,2294,2296,2298,2301],{"class":501,"line":818},[499,2286,2275],{"class":560},[499,2288,99],{"class":505},[499,2290,2291],{"class":547},"TextColor",[499,2293,575],{"class":505},[499,2295,1240],{"class":560},[499,2297,99],{"class":505},[499,2299,2300],{"class":560},"White",[499,2302,857],{"class":505},[499,2304,2305,2307,2309,2312,2314,2316,2318,2321,2323,2326],{"class":501,"line":837},[499,2306,2275],{"class":560},[499,2308,99],{"class":505},[499,2310,2311],{"class":547},"BgColor",[499,2313,575],{"class":505},[499,2315,1240],{"class":560},[499,2317,99],{"class":505},[499,2319,2320],{"class":547},"RGBHex",[499,2322,575],{"class":505},[499,2324,2325],{"class":658},"0x1A237E",[499,2327,2328],{"class":505},")),\n",[499,2330,2331],{"class":501,"line":860},[499,2332,2333],{"class":505},"            ),\n",[499,2335,2336,2338,2340,2343,2345,2347,2349,2351,2353,2356],{"class":501,"line":896},[499,2337,2233],{"class":560},[499,2339,99],{"class":505},[499,2341,2342],{"class":547},"TableStripe",[499,2344,575],{"class":505},[499,2346,1240],{"class":560},[499,2348,99],{"class":505},[499,2350,2320],{"class":547},[499,2352,575],{"class":505},[499,2354,2355],{"class":658},"0xF5F5F5",[499,2357,2328],{"class":505},[499,2359,2360],{"class":501,"line":902},[499,2361,2362],{"class":505},"        )\n",[499,2364,2365],{"class":501,"line":907},[499,2366,1050],{"class":505},[499,2368,2369],{"class":501,"line":924},[499,2370,2371],{"class":505},"})\n",[18,2373,2374,2377,2378,2381,2382,2385,2386,2388],{},[26,2375,2376],{},"ColumnWidths(50, 15, 15, 20)"," son ",[21,2379,2380],{},"porcentajes de la columna en la que vive la tabla",", no milímetros absolutos. Mete la tabla dentro de un ",[26,2383,2384],{},"r.Col(6, ...)"," y los mismos porcentajes siguen funcionando. Ese tipo de cosa no sale gratis con ",[26,2387,1301],{}," sin envolverlo.",[18,2390,2391],{},"Los saltos de línea son automáticos. Los saltos de página también — si la tabla se pasa del margen inferior, la cabecera se repite en la página siguiente.",[13,2393,2395],{"id":2394},"antes-después-3-texto-cjk-sin-el-baile-ritual","Antes / Después 3: texto CJK sin el baile ritual",[18,2397,2398,2399,2401],{},"Este fue el que me hizo dejar gofpdf. Para renderizar japonés en gofpdf llamas ",[26,2400,28],{},", le apuntas a un TTF en disco, fijas la fuente y rezas. El subsetting funciona la mayoría de las veces. Algunos TTF provocan colisiones de glyph-id y salen caracteres corruptos. Los mensajes de error no ayudan.",[18,2403,2404],{},[21,2405,488],{},[490,2407,2409],{"className":492,"code":2408,"language":494,"meta":495,"style":495},"pdf := gofpdf.New(\"P\", \"mm\", \"A4\", \"\")\npdf.AddUTF8Font(\"notosansjp\", \"\", \"NotoSansJP-Regular.ttf\")\npdf.AddPage()\npdf.SetFont(\"notosansjp\", \"\", 14)\npdf.Cell(0, 10, \"こんにちは、世界。\")\npdf.OutputFileAndClose(\"ja.pdf\")\n",[26,2410,2411,2454,2486,2496,2523,2550],{"__ignoreMap":495},[499,2412,2413,2416,2418,2420,2422,2424,2426,2428,2430,2432,2434,2436,2438,2440,2442,2444,2446,2448,2450,2452],{"class":501,"line":502},[499,2414,2415],{"class":560},"pdf ",[499,2417,564],{"class":505},[499,2419,567],{"class":560},[499,2421,99],{"class":505},[499,2423,572],{"class":547},[499,2425,575],{"class":505},[499,2427,578],{"class":505},[499,2429,582],{"class":581},[499,2431,578],{"class":505},[499,2433,587],{"class":505},[499,2435,527],{"class":505},[499,2437,592],{"class":581},[499,2439,578],{"class":505},[499,2441,587],{"class":505},[499,2443,527],{"class":505},[499,2445,601],{"class":581},[499,2447,578],{"class":505},[499,2449,587],{"class":505},[499,2451,608],{"class":505},[499,2453,611],{"class":505},[499,2455,2456,2458,2460,2462,2464,2466,2469,2471,2473,2475,2477,2479,2482,2484],{"class":501,"line":513},[499,2457,1240],{"class":560},[499,2459,99],{"class":505},[499,2461,28],{"class":547},[499,2463,575],{"class":505},[499,2465,578],{"class":505},[499,2467,2468],{"class":581},"notosansjp",[499,2470,578],{"class":505},[499,2472,587],{"class":505},[499,2474,608],{"class":505},[499,2476,587],{"class":505},[499,2478,527],{"class":505},[499,2480,2481],{"class":581},"NotoSansJP-Regular.ttf",[499,2483,578],{"class":505},[499,2485,611],{"class":505},[499,2487,2488,2490,2492,2494],{"class":501,"line":520},[499,2489,1240],{"class":560},[499,2491,99],{"class":505},[499,2493,622],{"class":547},[499,2495,625],{"class":505},[499,2497,2498,2500,2502,2504,2506,2508,2510,2512,2514,2516,2518,2521],{"class":501,"line":536},[499,2499,1240],{"class":560},[499,2501,99],{"class":505},[499,2503,635],{"class":547},[499,2505,575],{"class":505},[499,2507,578],{"class":505},[499,2509,2468],{"class":581},[499,2511,578],{"class":505},[499,2513,587],{"class":505},[499,2515,608],{"class":505},[499,2517,587],{"class":505},[499,2519,2520],{"class":658}," 14",[499,2522,611],{"class":505},[499,2524,2525,2527,2529,2531,2533,2535,2537,2539,2541,2543,2546,2548],{"class":501,"line":541},[499,2526,1240],{"class":560},[499,2528,99],{"class":505},[499,2530,671],{"class":547},[499,2532,575],{"class":505},[499,2534,1767],{"class":658},[499,2536,587],{"class":505},[499,2538,681],{"class":658},[499,2540,587],{"class":505},[499,2542,527],{"class":505},[499,2544,2545],{"class":581},"こんにちは、世界。",[499,2547,578],{"class":505},[499,2549,611],{"class":505},[499,2551,2552,2554,2556,2558,2560,2562,2565,2567],{"class":501,"line":557},[499,2553,1240],{"class":560},[499,2555,99],{"class":505},[499,2557,702],{"class":547},[499,2559,575],{"class":505},[499,2561,578],{"class":505},[499,2563,2564],{"class":581},"ja.pdf",[499,2566,578],{"class":505},[499,2568,611],{"class":505},[18,2570,2571,2572,2574,2575,2577],{},"Dos minas. El TTF tiene que existir en la ruta indicada en tiempo de ejecución (así que tu imagen Docker debe llevar la fuente). Y ",[26,2573,671],{}," con ancho ",[26,2576,1767],{}," significa \"hasta el margen derecho\", lo que con CJK suele recortar porque el estimador de anchura no maneja bien los glifos de ancho completo.",[18,2579,2580],{},[21,2581,724],{},[490,2583,2585],{"className":492,"code":2584,"language":494,"meta":495,"style":495},"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(\"NotoSansJP-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(\"NotoSansJP\", fontData),\n        gpdf.WithDefaultFont(\"NotoSansJP\", 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-2-3\")\n        })\n    })\n\n    data, _ := doc.Generate()\n    os.WriteFile(\"ja.pdf\", data, 0o644)\n}\n",[26,2586,2587,2593,2597,2603,2611,2619,2623,2631,2639,2647,2651,2655,2665,2693,2705,2719,2723,2727,2741,2759,2789,2814,2837,2841,2845,2859,2883,2913,2931,2950,2969,2973,2977,2982,3002,3030],{"__ignoreMap":495},[499,2588,2589,2591],{"class":501,"line":502},[499,2590,506],{"class":505},[499,2592,510],{"class":509},[499,2594,2595],{"class":501,"line":513},[499,2596,517],{"emptyLinePlaceholder":516},[499,2598,2599,2601],{"class":501,"line":520},[499,2600,524],{"class":523},[499,2602,746],{"class":505},[499,2604,2605,2607,2609],{"class":501,"line":536},[499,2606,751],{"class":505},[499,2608,754],{"class":509},[499,2610,533],{"class":505},[499,2612,2613,2615,2617],{"class":501,"line":541},[499,2614,751],{"class":505},[499,2616,763],{"class":509},[499,2618,533],{"class":505},[499,2620,2621],{"class":501,"line":557},[499,2622,517],{"emptyLinePlaceholder":516},[499,2624,2625,2627,2629],{"class":501,"line":614},[499,2626,751],{"class":505},[499,2628,776],{"class":509},[499,2630,533],{"class":505},[499,2632,2633,2635,2637],{"class":501,"line":628},[499,2634,751],{"class":505},[499,2636,785],{"class":509},[499,2638,533],{"class":505},[499,2640,2641,2643,2645],{"class":501,"line":664},[499,2642,751],{"class":505},[499,2644,794],{"class":509},[499,2646,533],{"class":505},[499,2648,2649],{"class":501,"line":695},[499,2650,611],{"class":505},[499,2652,2653],{"class":501,"line":716},[499,2654,517],{"emptyLinePlaceholder":516},[499,2656,2657,2659,2661,2663],{"class":501,"line":807},[499,2658,544],{"class":505},[499,2660,548],{"class":547},[499,2662,551],{"class":505},[499,2664,554],{"class":505},[499,2666,2667,2670,2672,2674,2676,2678,2680,2683,2685,2687,2689,2691],{"class":501,"line":818},[499,2668,2669],{"class":560},"    fontData",[499,2671,587],{"class":505},[499,2673,1066],{"class":560},[499,2675,564],{"class":505},[499,2677,1129],{"class":560},[499,2679,99],{"class":505},[499,2681,2682],{"class":547},"ReadFile",[499,2684,575],{"class":505},[499,2686,578],{"class":505},[499,2688,2481],{"class":581},[499,2690,578],{"class":505},[499,2692,611],{"class":505},[499,2694,2695,2697,2699,2701,2703],{"class":501,"line":837},[499,2696,1083],{"class":523},[499,2698,1066],{"class":560},[499,2700,1088],{"class":505},[499,2702,1091],{"class":505},[499,2704,554],{"class":505},[499,2706,2707,2709,2711,2713,2715,2717],{"class":501,"line":860},[499,2708,1099],{"class":560},[499,2710,99],{"class":505},[499,2712,1104],{"class":547},[499,2714,575],{"class":505},[499,2716,1109],{"class":560},[499,2718,611],{"class":505},[499,2720,2721],{"class":501,"line":896},[499,2722,1117],{"class":505},[499,2724,2725],{"class":501,"line":902},[499,2726,517],{"emptyLinePlaceholder":516},[499,2728,2729,2731,2733,2735,2737,2739],{"class":501,"line":907},[499,2730,821],{"class":560},[499,2732,564],{"class":505},[499,2734,826],{"class":560},[499,2736,99],{"class":505},[499,2738,831],{"class":547},[499,2740,834],{"class":505},[499,2742,2743,2745,2747,2749,2751,2753,2755,2757],{"class":501,"line":924},[499,2744,840],{"class":560},[499,2746,99],{"class":505},[499,2748,845],{"class":547},[499,2750,575],{"class":505},[499,2752,850],{"class":560},[499,2754,99],{"class":505},[499,2756,601],{"class":560},[499,2758,857],{"class":505},[499,2760,2761,2763,2765,2767,2769,2771,2773,2775,2777,2779,2781,2783,2785,2787],{"class":501,"line":957},[499,2762,840],{"class":560},[499,2764,99],{"class":505},[499,2766,867],{"class":547},[499,2768,575],{"class":505},[499,2770,850],{"class":560},[499,2772,99],{"class":505},[499,2774,876],{"class":547},[499,2776,575],{"class":505},[499,2778,850],{"class":560},[499,2780,99],{"class":505},[499,2782,885],{"class":547},[499,2784,575],{"class":505},[499,2786,890],{"class":658},[499,2788,893],{"class":505},[499,2790,2791,2793,2795,2798,2800,2802,2805,2807,2809,2812],{"class":501,"line":994},[499,2792,840],{"class":560},[499,2794,99],{"class":505},[499,2796,2797],{"class":547},"WithFont",[499,2799,575],{"class":505},[499,2801,578],{"class":505},[499,2803,2804],{"class":581},"NotoSansJP",[499,2806,578],{"class":505},[499,2808,587],{"class":505},[499,2810,2811],{"class":560}," fontData",[499,2813,857],{"class":505},[499,2815,2816,2818,2820,2823,2825,2827,2829,2831,2833,2835],{"class":501,"line":1041},[499,2817,840],{"class":560},[499,2819,99],{"class":505},[499,2821,2822],{"class":547},"WithDefaultFont",[499,2824,575],{"class":505},[499,2826,578],{"class":505},[499,2828,2804],{"class":581},[499,2830,578],{"class":505},[499,2832,587],{"class":505},[499,2834,2520],{"class":658},[499,2836,857],{"class":505},[499,2838,2839],{"class":501,"line":1047},[499,2840,899],{"class":505},[499,2842,2843],{"class":501,"line":1053},[499,2844,517],{"emptyLinePlaceholder":516},[499,2846,2847,2849,2851,2853,2855,2857],{"class":501,"line":1058},[499,2848,910],{"class":560},[499,2850,564],{"class":505},[499,2852,915],{"class":560},[499,2854,99],{"class":505},[499,2856,622],{"class":547},[499,2858,625],{"class":505},[499,2860,2861,2863,2865,2867,2869,2871,2873,2875,2877,2879,2881],{"class":501,"line":1080},[499,2862,927],{"class":560},[499,2864,99],{"class":505},[499,2866,932],{"class":547},[499,2868,935],{"class":505},[499,2870,939],{"class":938},[499,2872,942],{"class":505},[499,2874,945],{"class":509},[499,2876,99],{"class":505},[499,2878,950],{"class":509},[499,2880,213],{"class":505},[499,2882,554],{"class":505},[499,2884,2885,2887,2889,2891,2893,2895,2897,2899,2901,2903,2905,2907,2909,2911],{"class":501,"line":1096},[499,2886,960],{"class":560},[499,2888,99],{"class":505},[499,2890,965],{"class":547},[499,2892,575],{"class":505},[499,2894,970],{"class":658},[499,2896,587],{"class":505},[499,2898,975],{"class":505},[499,2900,978],{"class":938},[499,2902,942],{"class":505},[499,2904,945],{"class":509},[499,2906,99],{"class":505},[499,2908,987],{"class":509},[499,2910,213],{"class":505},[499,2912,554],{"class":505},[499,2914,2915,2917,2919,2921,2923,2925,2927,2929],{"class":501,"line":1114},[499,2916,997],{"class":560},[499,2918,99],{"class":505},[499,2920,1002],{"class":547},[499,2922,575],{"class":505},[499,2924,578],{"class":505},[499,2926,2545],{"class":581},[499,2928,578],{"class":505},[499,2930,611],{"class":505},[499,2932,2933,2935,2937,2939,2941,2943,2946,2948],{"class":501,"line":1120},[499,2934,997],{"class":560},[499,2936,99],{"class":505},[499,2938,1002],{"class":547},[499,2940,575],{"class":505},[499,2942,578],{"class":505},[499,2944,2945],{"class":581},"吾輩は猫である。名前はまだ無い。",[499,2947,578],{"class":505},[499,2949,611],{"class":505},[499,2951,2952,2954,2956,2958,2960,2962,2965,2967],{"class":501,"line":1166},[499,2953,997],{"class":560},[499,2955,99],{"class":505},[499,2957,1002],{"class":547},[499,2959,575],{"class":505},[499,2961,578],{"class":505},[499,2963,2964],{"class":581},"東京都渋谷区神宮前1-2-3",[499,2966,578],{"class":505},[499,2968,611],{"class":505},[499,2970,2971],{"class":501,"line":1181},[499,2972,1044],{"class":505},[499,2974,2975],{"class":501,"line":1186},[499,2976,1050],{"class":505},[499,2978,2980],{"class":501,"line":2979},33,[499,2981,517],{"emptyLinePlaceholder":516},[499,2983,2985,2987,2989,2992,2994,2996,2998,3000],{"class":501,"line":2984},34,[499,2986,1061],{"class":560},[499,2988,587],{"class":505},[499,2990,2991],{"class":560}," _ ",[499,2993,564],{"class":505},[499,2995,915],{"class":560},[499,2997,99],{"class":505},[499,2999,1075],{"class":547},[499,3001,625],{"class":505},[499,3003,3005,3008,3010,3012,3014,3016,3018,3020,3022,3024,3026,3028],{"class":501,"line":3004},35,[499,3006,3007],{"class":560},"    os",[499,3009,99],{"class":505},[499,3011,1134],{"class":547},[499,3013,575],{"class":505},[499,3015,578],{"class":505},[499,3017,2564],{"class":581},[499,3019,578],{"class":505},[499,3021,587],{"class":505},[499,3023,1147],{"class":560},[499,3025,587],{"class":505},[499,3027,1152],{"class":658},[499,3029,611],{"class":505},[499,3031,3033],{"class":501,"line":3032},36,[499,3034,719],{"class":505},[18,3036,3037],{},"Dos diferencias.",[18,3039,3040,3041,3044,3045,3048],{},"Primero, pasas ",[21,3042,3043],{},"bytes",", no una ruta. Embebe el TTF con ",[26,3046,3047],{},"//go:embed"," y el binario queda autocontenido. Adiós al \"font not found\" en producción porque alguien olvidó montar un volumen.",[18,3050,3051],{},"Segundo, el subsetter TrueType de gpdf entiende los formatos cmap CJK (4, 6, 12) y la codificación Identity-H. El PDF de salida solo lleva los glifos que usas realmente — embebiendo NotoSansJP en una factura de 200 caracteres sale un subset de ~30 KB, no un embed completo de 4 MB. Si alguna vez viste a gofpdf escribir un PDF de 5 MB por una página en japonés, esto es lo primero que notas.",[18,3053,3054],{},"Para un recorrido más profundo de opciones CJK específicas — IPAex Gothic, Source Han Sans, cadenas de fallback — se publicará un post complementario.",[13,3056,3058],{"id":3057},"antes-después-4-cabecera-en-cada-página-número-de-página-en-el-pie","Antes / Después 4: cabecera en cada página, número de página en el pie",[18,3060,3061,3062,109,3065,3068,3069,3072,3073,109,3075,99],{},"El patrón de gofpdf para el cromado repetido es ",[26,3063,3064],{},"SetHeaderFunc",[26,3066,3067],{},"SetFooterFunc"," — ambos reciben un ",[26,3070,3071],{},"func()"," que corre contra el cursor actual. Los números de página vienen de ",[26,3074,394],{},[26,3076,3077],{},"pdf.AliasNbPages()",[18,3079,3080],{},[21,3081,488],{},[490,3083,3085],{"className":492,"code":3084,"language":494,"meta":495,"style":495},"pdf := gofpdf.New(\"P\", \"mm\", \"A4\", \"\")\npdf.SetHeaderFunc(func() {\n    pdf.SetFont(\"Arial\", \"B\", 12)\n    pdf.Cell(0, 10, \"ACME Corporación\")\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(\"Página %d/{nb}\", pdf.PageNo()),\n        \"\", 0, \"C\", false, 0, \"\")\n})\npdf.AliasNbPages(\"\")\npdf.AddPage()\n// ... cuerpo ...\n",[26,3086,3087,3129,3142,3173,3200,3216,3220,3232,3248,3279,3298,3337,3368,3372,3388,3398],{"__ignoreMap":495},[499,3088,3089,3091,3093,3095,3097,3099,3101,3103,3105,3107,3109,3111,3113,3115,3117,3119,3121,3123,3125,3127],{"class":501,"line":502},[499,3090,2415],{"class":560},[499,3092,564],{"class":505},[499,3094,567],{"class":560},[499,3096,99],{"class":505},[499,3098,572],{"class":547},[499,3100,575],{"class":505},[499,3102,578],{"class":505},[499,3104,582],{"class":581},[499,3106,578],{"class":505},[499,3108,587],{"class":505},[499,3110,527],{"class":505},[499,3112,592],{"class":581},[499,3114,578],{"class":505},[499,3116,587],{"class":505},[499,3118,527],{"class":505},[499,3120,601],{"class":581},[499,3122,578],{"class":505},[499,3124,587],{"class":505},[499,3126,608],{"class":505},[499,3128,611],{"class":505},[499,3130,3131,3133,3135,3137,3140],{"class":501,"line":513},[499,3132,1240],{"class":560},[499,3134,99],{"class":505},[499,3136,3064],{"class":547},[499,3138,3139],{"class":505},"(func()",[499,3141,554],{"class":505},[499,3143,3144,3146,3148,3150,3152,3154,3156,3158,3160,3162,3164,3166,3168,3171],{"class":501,"line":520},[499,3145,617],{"class":560},[499,3147,99],{"class":505},[499,3149,635],{"class":547},[499,3151,575],{"class":505},[499,3153,578],{"class":505},[499,3155,642],{"class":581},[499,3157,578],{"class":505},[499,3159,587],{"class":505},[499,3161,527],{"class":505},[499,3163,651],{"class":581},[499,3165,578],{"class":505},[499,3167,587],{"class":505},[499,3169,3170],{"class":658}," 12",[499,3172,611],{"class":505},[499,3174,3175,3177,3179,3181,3183,3185,3187,3189,3191,3193,3196,3198],{"class":501,"line":536},[499,3176,617],{"class":560},[499,3178,99],{"class":505},[499,3180,671],{"class":547},[499,3182,575],{"class":505},[499,3184,1767],{"class":658},[499,3186,587],{"class":505},[499,3188,681],{"class":658},[499,3190,587],{"class":505},[499,3192,527],{"class":505},[499,3194,3195],{"class":581},"ACME Corporación",[499,3197,578],{"class":505},[499,3199,611],{"class":505},[499,3201,3202,3204,3206,3209,3211,3214],{"class":501,"line":541},[499,3203,617],{"class":560},[499,3205,99],{"class":505},[499,3207,3208],{"class":547},"Ln",[499,3210,575],{"class":505},[499,3212,3213],{"class":658},"15",[499,3215,611],{"class":505},[499,3217,3218],{"class":501,"line":557},[499,3219,2371],{"class":505},[499,3221,3222,3224,3226,3228,3230],{"class":501,"line":614},[499,3223,1240],{"class":560},[499,3225,99],{"class":505},[499,3227,3067],{"class":547},[499,3229,3139],{"class":505},[499,3231,554],{"class":505},[499,3233,3234,3236,3238,3241,3244,3246],{"class":501,"line":628},[499,3235,617],{"class":560},[499,3237,99],{"class":505},[499,3239,3240],{"class":547},"SetY",[499,3242,3243],{"class":505},"(-",[499,3245,3213],{"class":658},[499,3247,611],{"class":505},[499,3249,3250,3252,3254,3256,3258,3260,3262,3264,3266,3268,3271,3273,3275,3277],{"class":501,"line":664},[499,3251,617],{"class":560},[499,3253,99],{"class":505},[499,3255,635],{"class":547},[499,3257,575],{"class":505},[499,3259,578],{"class":505},[499,3261,642],{"class":581},[499,3263,578],{"class":505},[499,3265,587],{"class":505},[499,3267,527],{"class":505},[499,3269,3270],{"class":581},"I",[499,3272,578],{"class":505},[499,3274,587],{"class":505},[499,3276,1311],{"class":658},[499,3278,611],{"class":505},[499,3280,3281,3283,3285,3287,3289,3291,3293,3295],{"class":501,"line":695},[499,3282,617],{"class":560},[499,3284,99],{"class":505},[499,3286,1301],{"class":547},[499,3288,575],{"class":505},[499,3290,1767],{"class":658},[499,3292,587],{"class":505},[499,3294,681],{"class":658},[499,3296,3297],{"class":505},",\n",[499,3299,3300,3303,3305,3308,3310,3312,3315,3319,3322,3324,3326,3329,3331,3334],{"class":501,"line":716},[499,3301,3302],{"class":560},"        fmt",[499,3304,99],{"class":505},[499,3306,3307],{"class":547},"Sprintf",[499,3309,575],{"class":505},[499,3311,578],{"class":505},[499,3313,3314],{"class":581},"Página ",[499,3316,3318],{"class":3317},"swJcz","%d",[499,3320,3321],{"class":581},"/{nb}",[499,3323,578],{"class":505},[499,3325,587],{"class":505},[499,3327,3328],{"class":560}," pdf",[499,3330,99],{"class":505},[499,3332,3333],{"class":547},"PageNo",[499,3335,3336],{"class":505},"()),\n",[499,3338,3339,3342,3344,3346,3348,3350,3352,3354,3356,3358,3360,3362,3364,3366],{"class":501,"line":807},[499,3340,3341],{"class":505},"        \"\"",[499,3343,587],{"class":505},[499,3345,1334],{"class":658},[499,3347,587],{"class":505},[499,3349,527],{"class":505},[499,3351,1404],{"class":581},[499,3353,578],{"class":505},[499,3355,587],{"class":505},[499,3357,1793],{"class":1348},[499,3359,587],{"class":505},[499,3361,1334],{"class":658},[499,3363,587],{"class":505},[499,3365,608],{"class":505},[499,3367,611],{"class":505},[499,3369,3370],{"class":501,"line":818},[499,3371,2371],{"class":505},[499,3373,3374,3376,3378,3381,3383,3386],{"class":501,"line":837},[499,3375,1240],{"class":560},[499,3377,99],{"class":505},[499,3379,3380],{"class":547},"AliasNbPages",[499,3382,575],{"class":505},[499,3384,3385],{"class":505},"\"\"",[499,3387,611],{"class":505},[499,3389,3390,3392,3394,3396],{"class":501,"line":860},[499,3391,1240],{"class":560},[499,3393,99],{"class":505},[499,3395,622],{"class":547},[499,3397,625],{"class":505},[499,3399,3400],{"class":501,"line":896},[499,3401,3403],{"class":3402},"sHwdD","// ... cuerpo ...\n",[18,3405,3406,3409],{},[26,3407,3408],{},"{nb}"," es un centinela que gofpdf sustituye al escribir con el número total de páginas. Funciona, pero es de esas cosas que \"hay que saber\".",[18,3411,3412],{},[21,3413,724],{},[490,3415,3417],{"className":492,"code":3416,"language":494,"meta":495,"style":495},"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 Corporación\", 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 Corporación\",\n                template.FontSize(8), template.TextColor(pdf.Gray(0.5)))\n        })\n        r.Col(6, func(c *template.ColBuilder) {\n            // \"Página X / Y\" — ambas partes son placeholders\n            // que el motor de layout resuelve tras la paginació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(\"Contenido de la página %d.\", i+1))\n        })\n    })\n}\n",[26,3418,3419,3434,3453,3483,3487,3491,3518,3543,3573,3613,3648,3672,3676,3680,3684,3688,3713,3737,3768,3786,3822,3826,3856,3861,3866,3886,3920,3924,3928,3932,3936,3967,3981,4005,4035,4076,4080,4085],{"__ignoreMap":495},[499,3420,3421,3424,3426,3428,3430,3432],{"class":501,"line":502},[499,3422,3423],{"class":560},"doc ",[499,3425,564],{"class":505},[499,3427,826],{"class":560},[499,3429,99],{"class":505},[499,3431,831],{"class":547},[499,3433,834],{"class":505},[499,3435,3436,3439,3441,3443,3445,3447,3449,3451],{"class":501,"line":513},[499,3437,3438],{"class":560},"    gpdf",[499,3440,99],{"class":505},[499,3442,845],{"class":547},[499,3444,575],{"class":505},[499,3446,850],{"class":560},[499,3448,99],{"class":505},[499,3450,601],{"class":560},[499,3452,857],{"class":505},[499,3454,3455,3457,3459,3461,3463,3465,3467,3469,3471,3473,3475,3477,3479,3481],{"class":501,"line":520},[499,3456,3438],{"class":560},[499,3458,99],{"class":505},[499,3460,867],{"class":547},[499,3462,575],{"class":505},[499,3464,850],{"class":560},[499,3466,99],{"class":505},[499,3468,876],{"class":547},[499,3470,575],{"class":505},[499,3472,850],{"class":560},[499,3474,99],{"class":505},[499,3476,885],{"class":547},[499,3478,575],{"class":505},[499,3480,890],{"class":658},[499,3482,893],{"class":505},[499,3484,3485],{"class":501,"line":536},[499,3486,611],{"class":505},[499,3488,3489],{"class":501,"line":541},[499,3490,517],{"emptyLinePlaceholder":516},[499,3492,3493,3496,3498,3501,3503,3505,3507,3509,3511,3514,3516],{"class":501,"line":557},[499,3494,3495],{"class":560},"doc",[499,3497,99],{"class":505},[499,3499,3500],{"class":547},"Header",[499,3502,935],{"class":505},[499,3504,18],{"class":938},[499,3506,942],{"class":505},[499,3508,945],{"class":509},[499,3510,99],{"class":505},[499,3512,3513],{"class":509},"PageBuilder",[499,3515,213],{"class":505},[499,3517,554],{"class":505},[499,3519,3520,3523,3525,3527,3529,3531,3533,3535,3537,3539,3541],{"class":501,"line":614},[499,3521,3522],{"class":560},"    p",[499,3524,99],{"class":505},[499,3526,932],{"class":547},[499,3528,935],{"class":505},[499,3530,939],{"class":938},[499,3532,942],{"class":505},[499,3534,945],{"class":509},[499,3536,99],{"class":505},[499,3538,950],{"class":509},[499,3540,213],{"class":505},[499,3542,554],{"class":505},[499,3544,3545,3547,3549,3551,3553,3555,3557,3559,3561,3563,3565,3567,3569,3571],{"class":501,"line":628},[499,3546,960],{"class":560},[499,3548,99],{"class":505},[499,3550,965],{"class":547},[499,3552,575],{"class":505},[499,3554,970],{"class":658},[499,3556,587],{"class":505},[499,3558,975],{"class":505},[499,3560,978],{"class":938},[499,3562,942],{"class":505},[499,3564,945],{"class":509},[499,3566,99],{"class":505},[499,3568,987],{"class":509},[499,3570,213],{"class":505},[499,3572,554],{"class":505},[499,3574,3575,3577,3579,3581,3583,3585,3587,3589,3591,3593,3595,3597,3600,3602,3604,3606,3608,3610],{"class":501,"line":664},[499,3576,997],{"class":560},[499,3578,99],{"class":505},[499,3580,1002],{"class":547},[499,3582,575],{"class":505},[499,3584,578],{"class":505},[499,3586,3195],{"class":581},[499,3588,578],{"class":505},[499,3590,587],{"class":505},[499,3592,1015],{"class":560},[499,3594,99],{"class":505},[499,3596,1035],{"class":547},[499,3598,3599],{"class":505},"(),",[499,3601,1015],{"class":560},[499,3603,99],{"class":505},[499,3605,1020],{"class":547},[499,3607,575],{"class":505},[499,3609,970],{"class":658},[499,3611,3612],{"class":505},"))\n",[499,3614,3615,3617,3619,3622,3624,3626,3628,3631,3633,3635,3637,3640,3642,3645],{"class":501,"line":695},[499,3616,997],{"class":560},[499,3618,99],{"class":505},[499,3620,3621],{"class":547},"Line",[499,3623,575],{"class":505},[499,3625,945],{"class":560},[499,3627,99],{"class":505},[499,3629,3630],{"class":547},"LineColor",[499,3632,575],{"class":505},[499,3634,1240],{"class":560},[499,3636,99],{"class":505},[499,3638,3639],{"class":547},"Gray",[499,3641,575],{"class":505},[499,3643,3644],{"class":658},"0.7",[499,3646,3647],{"class":505},")))\n",[499,3649,3650,3652,3654,3657,3659,3661,3663,3665,3667,3670],{"class":501,"line":716},[499,3651,997],{"class":560},[499,3653,99],{"class":505},[499,3655,3656],{"class":547},"Spacer",[499,3658,575],{"class":505},[499,3660,850],{"class":560},[499,3662,99],{"class":505},[499,3664,885],{"class":547},[499,3666,575],{"class":505},[499,3668,3669],{"class":658},"4",[499,3671,3612],{"class":505},[499,3673,3674],{"class":501,"line":807},[499,3675,1044],{"class":505},[499,3677,3678],{"class":501,"line":818},[499,3679,1050],{"class":505},[499,3681,3682],{"class":501,"line":837},[499,3683,2371],{"class":505},[499,3685,3686],{"class":501,"line":860},[499,3687,517],{"emptyLinePlaceholder":516},[499,3689,3690,3692,3694,3697,3699,3701,3703,3705,3707,3709,3711],{"class":501,"line":896},[499,3691,3495],{"class":560},[499,3693,99],{"class":505},[499,3695,3696],{"class":547},"Footer",[499,3698,935],{"class":505},[499,3700,18],{"class":938},[499,3702,942],{"class":505},[499,3704,945],{"class":509},[499,3706,99],{"class":505},[499,3708,3513],{"class":509},[499,3710,213],{"class":505},[499,3712,554],{"class":505},[499,3714,3715,3717,3719,3721,3723,3725,3727,3729,3731,3733,3735],{"class":501,"line":902},[499,3716,3522],{"class":560},[499,3718,99],{"class":505},[499,3720,932],{"class":547},[499,3722,935],{"class":505},[499,3724,939],{"class":938},[499,3726,942],{"class":505},[499,3728,945],{"class":509},[499,3730,99],{"class":505},[499,3732,950],{"class":509},[499,3734,213],{"class":505},[499,3736,554],{"class":505},[499,3738,3739,3741,3743,3745,3747,3750,3752,3754,3756,3758,3760,3762,3764,3766],{"class":501,"line":907},[499,3740,960],{"class":560},[499,3742,99],{"class":505},[499,3744,965],{"class":547},[499,3746,575],{"class":505},[499,3748,3749],{"class":658},"6",[499,3751,587],{"class":505},[499,3753,975],{"class":505},[499,3755,978],{"class":938},[499,3757,942],{"class":505},[499,3759,945],{"class":509},[499,3761,99],{"class":505},[499,3763,987],{"class":509},[499,3765,213],{"class":505},[499,3767,554],{"class":505},[499,3769,3770,3772,3774,3776,3778,3780,3782,3784],{"class":501,"line":924},[499,3771,997],{"class":560},[499,3773,99],{"class":505},[499,3775,1002],{"class":547},[499,3777,575],{"class":505},[499,3779,578],{"class":505},[499,3781,3195],{"class":581},[499,3783,578],{"class":505},[499,3785,3297],{"class":505},[499,3787,3788,3790,3792,3794,3796,3799,3801,3803,3805,3807,3809,3811,3813,3815,3817,3820],{"class":501,"line":957},[499,3789,2275],{"class":560},[499,3791,99],{"class":505},[499,3793,1020],{"class":547},[499,3795,575],{"class":505},[499,3797,3798],{"class":658},"8",[499,3800,1028],{"class":505},[499,3802,1015],{"class":560},[499,3804,99],{"class":505},[499,3806,2291],{"class":547},[499,3808,575],{"class":505},[499,3810,1240],{"class":560},[499,3812,99],{"class":505},[499,3814,3639],{"class":547},[499,3816,575],{"class":505},[499,3818,3819],{"class":658},"0.5",[499,3821,3647],{"class":505},[499,3823,3824],{"class":501,"line":994},[499,3825,1044],{"class":505},[499,3827,3828,3830,3832,3834,3836,3838,3840,3842,3844,3846,3848,3850,3852,3854],{"class":501,"line":1041},[499,3829,960],{"class":560},[499,3831,99],{"class":505},[499,3833,965],{"class":547},[499,3835,575],{"class":505},[499,3837,3749],{"class":658},[499,3839,587],{"class":505},[499,3841,975],{"class":505},[499,3843,978],{"class":938},[499,3845,942],{"class":505},[499,3847,945],{"class":509},[499,3849,99],{"class":505},[499,3851,987],{"class":509},[499,3853,213],{"class":505},[499,3855,554],{"class":505},[499,3857,3858],{"class":501,"line":1047},[499,3859,3860],{"class":3402},"            // \"Página X / Y\" — ambas partes son placeholders\n",[499,3862,3863],{"class":501,"line":1053},[499,3864,3865],{"class":3402},"            // que el motor de layout resuelve tras la paginación.\n",[499,3867,3868,3870,3872,3875,3877,3879,3881,3884],{"class":501,"line":1058},[499,3869,997],{"class":560},[499,3871,99],{"class":505},[499,3873,3874],{"class":547},"PageNumber",[499,3876,575],{"class":505},[499,3878,945],{"class":560},[499,3880,99],{"class":505},[499,3882,3883],{"class":547},"AlignRight",[499,3885,2282],{"class":505},[499,3887,3888,3890,3892,3894,3896,3898,3900,3902,3904,3906,3908,3910,3912,3914,3916,3918],{"class":501,"line":1080},[499,3889,2275],{"class":560},[499,3891,99],{"class":505},[499,3893,1020],{"class":547},[499,3895,575],{"class":505},[499,3897,3798],{"class":658},[499,3899,1028],{"class":505},[499,3901,1015],{"class":560},[499,3903,99],{"class":505},[499,3905,2291],{"class":547},[499,3907,575],{"class":505},[499,3909,1240],{"class":560},[499,3911,99],{"class":505},[499,3913,3639],{"class":547},[499,3915,575],{"class":505},[499,3917,3819],{"class":658},[499,3919,3647],{"class":505},[499,3921,3922],{"class":501,"line":1096},[499,3923,1044],{"class":505},[499,3925,3926],{"class":501,"line":1114},[499,3927,1050],{"class":505},[499,3929,3930],{"class":501,"line":1120},[499,3931,2371],{"class":505},[499,3933,3934],{"class":501,"line":1166},[499,3935,517],{"emptyLinePlaceholder":516},[499,3937,3938,3940,3943,3945,3947,3950,3952,3955,3957,3959,3962,3965],{"class":501,"line":1181},[499,3939,1722],{"class":523},[499,3941,3942],{"class":560}," i ",[499,3944,564],{"class":505},[499,3946,1334],{"class":658},[499,3948,3949],{"class":505},";",[499,3951,3942],{"class":560},[499,3953,3954],{"class":505},"\u003C",[499,3956,681],{"class":658},[499,3958,3949],{"class":505},[499,3960,3961],{"class":560}," i",[499,3963,3964],{"class":505},"++",[499,3966,554],{"class":505},[499,3968,3969,3971,3973,3975,3977,3979],{"class":501,"line":1186},[499,3970,910],{"class":560},[499,3972,564],{"class":505},[499,3974,915],{"class":560},[499,3976,99],{"class":505},[499,3978,622],{"class":547},[499,3980,625],{"class":505},[499,3982,3983,3985,3987,3989,3991,3993,3995,3997,3999,4001,4003],{"class":501,"line":2979},[499,3984,927],{"class":560},[499,3986,99],{"class":505},[499,3988,932],{"class":547},[499,3990,935],{"class":505},[499,3992,939],{"class":938},[499,3994,942],{"class":505},[499,3996,945],{"class":509},[499,3998,99],{"class":505},[499,4000,950],{"class":509},[499,4002,213],{"class":505},[499,4004,554],{"class":505},[499,4006,4007,4009,4011,4013,4015,4017,4019,4021,4023,4025,4027,4029,4031,4033],{"class":501,"line":2984},[499,4008,960],{"class":560},[499,4010,99],{"class":505},[499,4012,965],{"class":547},[499,4014,575],{"class":505},[499,4016,970],{"class":658},[499,4018,587],{"class":505},[499,4020,975],{"class":505},[499,4022,978],{"class":938},[499,4024,942],{"class":505},[499,4026,945],{"class":509},[499,4028,99],{"class":505},[499,4030,987],{"class":509},[499,4032,213],{"class":505},[499,4034,554],{"class":505},[499,4036,4037,4039,4041,4043,4045,4048,4050,4052,4054,4056,4059,4061,4063,4065,4067,4069,4072,4074],{"class":501,"line":3004},[499,4038,997],{"class":560},[499,4040,99],{"class":505},[499,4042,1002],{"class":547},[499,4044,575],{"class":505},[499,4046,4047],{"class":560},"fmt",[499,4049,99],{"class":505},[499,4051,3307],{"class":547},[499,4053,575],{"class":505},[499,4055,578],{"class":505},[499,4057,4058],{"class":581},"Contenido de la página ",[499,4060,3318],{"class":3317},[499,4062,99],{"class":581},[499,4064,578],{"class":505},[499,4066,587],{"class":505},[499,4068,3961],{"class":560},[499,4070,4071],{"class":505},"+",[499,4073,1327],{"class":658},[499,4075,3612],{"class":505},[499,4077,4078],{"class":501,"line":3032},[499,4079,1044],{"class":505},[499,4081,4083],{"class":501,"line":4082},37,[499,4084,1050],{"class":505},[499,4086,4088],{"class":501,"line":4087},38,[499,4089,719],{"class":505},[18,4091,4092,109,4094,4097,4098,4100,4101,4104],{},[26,4093,3874],{},[26,4095,4096],{},"TotalPages"," son placeholders. Se expanden tras la paginación, cuando el motor de layout ya sabe cuántas páginas hay. Sin centinela ",[26,4099,3408],{},", sin ",[26,4102,4103],{},"SetY(-15)"," manual para clavar el pie abajo — el pie es solo un árbol, y el motor le reserva espacio automáticamente en cada página.",[13,4106,4108],{"id":4107},"antes-después-5-producir-bytes-para-un-handler-http","Antes / Después 5: producir bytes para un handler HTTP",[18,4110,4111,4112,4114,4115,4118,4119,4122],{},"La mayoría del código gofpdf en producción no escribe a un archivo. Escribe a un ",[26,4113,1211],{}," — normalmente un ",[26,4116,4117],{},"http.ResponseWriter"," devolviendo ",[26,4120,4121],{},"application/pdf"," al navegador. En este par la API de gpdf es la que más se parece a la de gofpdf.",[18,4124,4125],{},[21,4126,488],{},[490,4128,4130],{"className":492,"code":4129,"language":494,"meta":495,"style":495},"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, \"Generado a las \"+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,4131,4132,4171,4213,4223,4249,4301,4305,4338,4367,4397,4401],{"__ignoreMap":495},[499,4133,4134,4136,4139,4141,4144,4147,4149,4152,4154,4157,4159,4162,4164,4167,4169],{"class":501,"line":502},[499,4135,544],{"class":505},[499,4137,4138],{"class":547}," handler",[499,4140,575],{"class":505},[499,4142,4143],{"class":938},"w",[499,4145,4146],{"class":509}," http",[499,4148,99],{"class":505},[499,4150,4151],{"class":509},"ResponseWriter",[499,4153,587],{"class":505},[499,4155,4156],{"class":938}," r",[499,4158,942],{"class":505},[499,4160,4161],{"class":509},"http",[499,4163,99],{"class":505},[499,4165,4166],{"class":509},"Request",[499,4168,213],{"class":505},[499,4170,554],{"class":505},[499,4172,4173,4175,4177,4179,4181,4183,4185,4187,4189,4191,4193,4195,4197,4199,4201,4203,4205,4207,4209,4211],{"class":501,"line":513},[499,4174,561],{"class":560},[499,4176,564],{"class":505},[499,4178,567],{"class":560},[499,4180,99],{"class":505},[499,4182,572],{"class":547},[499,4184,575],{"class":505},[499,4186,578],{"class":505},[499,4188,582],{"class":581},[499,4190,578],{"class":505},[499,4192,587],{"class":505},[499,4194,527],{"class":505},[499,4196,592],{"class":581},[499,4198,578],{"class":505},[499,4200,587],{"class":505},[499,4202,527],{"class":505},[499,4204,601],{"class":581},[499,4206,578],{"class":505},[499,4208,587],{"class":505},[499,4210,608],{"class":505},[499,4212,611],{"class":505},[499,4214,4215,4217,4219,4221],{"class":501,"line":520},[499,4216,617],{"class":560},[499,4218,99],{"class":505},[499,4220,622],{"class":547},[499,4222,625],{"class":505},[499,4224,4225,4227,4229,4231,4233,4235,4237,4239,4241,4243,4245,4247],{"class":501,"line":536},[499,4226,617],{"class":560},[499,4228,99],{"class":505},[499,4230,635],{"class":547},[499,4232,575],{"class":505},[499,4234,578],{"class":505},[499,4236,642],{"class":581},[499,4238,578],{"class":505},[499,4240,587],{"class":505},[499,4242,608],{"class":505},[499,4244,587],{"class":505},[499,4246,3170],{"class":658},[499,4248,611],{"class":505},[499,4250,4251,4253,4255,4257,4259,4261,4263,4265,4267,4269,4272,4274,4276,4279,4281,4284,4287,4290,4292,4294,4296,4299],{"class":501,"line":541},[499,4252,617],{"class":560},[499,4254,99],{"class":505},[499,4256,671],{"class":547},[499,4258,575],{"class":505},[499,4260,1767],{"class":658},[499,4262,587],{"class":505},[499,4264,681],{"class":658},[499,4266,587],{"class":505},[499,4268,527],{"class":505},[499,4270,4271],{"class":581},"Generado a las ",[499,4273,578],{"class":505},[499,4275,4071],{"class":505},[499,4277,4278],{"class":560},"time",[499,4280,99],{"class":505},[499,4282,4283],{"class":547},"Now",[499,4285,4286],{"class":505},"().",[499,4288,4289],{"class":547},"Format",[499,4291,575],{"class":505},[499,4293,4278],{"class":560},[499,4295,99],{"class":505},[499,4297,4298],{"class":560},"RFC3339",[499,4300,3612],{"class":505},[499,4302,4303],{"class":501,"line":557},[499,4304,517],{"emptyLinePlaceholder":516},[499,4306,4307,4310,4312,4314,4316,4319,4321,4323,4326,4328,4330,4332,4334,4336],{"class":501,"line":614},[499,4308,4309],{"class":560},"    w",[499,4311,99],{"class":505},[499,4313,3500],{"class":547},[499,4315,4286],{"class":505},[499,4317,4318],{"class":547},"Set",[499,4320,575],{"class":505},[499,4322,578],{"class":505},[499,4324,4325],{"class":581},"Content-Type",[499,4327,578],{"class":505},[499,4329,587],{"class":505},[499,4331,527],{"class":505},[499,4333,4121],{"class":581},[499,4335,578],{"class":505},[499,4337,611],{"class":505},[499,4339,4340,4342,4344,4346,4348,4350,4353,4355,4357,4359,4361,4363,4365],{"class":501,"line":628},[499,4341,1083],{"class":523},[499,4343,1066],{"class":560},[499,4345,564],{"class":505},[499,4347,3328],{"class":560},[499,4349,99],{"class":505},[499,4351,4352],{"class":547},"Output",[499,4354,575],{"class":505},[499,4356,4143],{"class":560},[499,4358,1155],{"class":505},[499,4360,1066],{"class":560},[499,4362,1088],{"class":505},[499,4364,1091],{"class":505},[499,4366,554],{"class":505},[499,4368,4369,4372,4374,4377,4379,4381,4383,4386,4388,4390,4392,4395],{"class":501,"line":664},[499,4370,4371],{"class":560},"        http",[499,4373,99],{"class":505},[499,4375,4376],{"class":547},"Error",[499,4378,575],{"class":505},[499,4380,4143],{"class":560},[499,4382,587],{"class":505},[499,4384,4385],{"class":560}," err",[499,4387,99],{"class":505},[499,4389,4376],{"class":547},[499,4391,3599],{"class":505},[499,4393,4394],{"class":658}," 500",[499,4396,611],{"class":505},[499,4398,4399],{"class":501,"line":695},[499,4400,1117],{"class":505},[499,4402,4403],{"class":501,"line":716},[499,4404,719],{"class":505},[18,4406,4407],{},[21,4408,724],{},[490,4410,4412],{"className":492,"code":4411,"language":494,"meta":495,"style":495},"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(\"Generado a las \" + 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,4413,4414,4446,4460,4478,4508,4512,4516,4530,4554,4584,4624,4628,4632,4636,4666,4695,4721,4725],{"__ignoreMap":495},[499,4415,4416,4418,4420,4422,4424,4426,4428,4430,4432,4434,4436,4438,4440,4442,4444],{"class":501,"line":502},[499,4417,544],{"class":505},[499,4419,4138],{"class":547},[499,4421,575],{"class":505},[499,4423,4143],{"class":938},[499,4425,4146],{"class":509},[499,4427,99],{"class":505},[499,4429,4151],{"class":509},[499,4431,587],{"class":505},[499,4433,4156],{"class":938},[499,4435,942],{"class":505},[499,4437,4161],{"class":509},[499,4439,99],{"class":505},[499,4441,4166],{"class":509},[499,4443,213],{"class":505},[499,4445,554],{"class":505},[499,4447,4448,4450,4452,4454,4456,4458],{"class":501,"line":513},[499,4449,821],{"class":560},[499,4451,564],{"class":505},[499,4453,826],{"class":560},[499,4455,99],{"class":505},[499,4457,831],{"class":547},[499,4459,834],{"class":505},[499,4461,4462,4464,4466,4468,4470,4472,4474,4476],{"class":501,"line":520},[499,4463,840],{"class":560},[499,4465,99],{"class":505},[499,4467,845],{"class":547},[499,4469,575],{"class":505},[499,4471,850],{"class":560},[499,4473,99],{"class":505},[499,4475,601],{"class":560},[499,4477,857],{"class":505},[499,4479,4480,4482,4484,4486,4488,4490,4492,4494,4496,4498,4500,4502,4504,4506],{"class":501,"line":536},[499,4481,840],{"class":560},[499,4483,99],{"class":505},[499,4485,867],{"class":547},[499,4487,575],{"class":505},[499,4489,850],{"class":560},[499,4491,99],{"class":505},[499,4493,876],{"class":547},[499,4495,575],{"class":505},[499,4497,850],{"class":560},[499,4499,99],{"class":505},[499,4501,885],{"class":547},[499,4503,575],{"class":505},[499,4505,890],{"class":658},[499,4507,893],{"class":505},[499,4509,4510],{"class":501,"line":541},[499,4511,899],{"class":505},[499,4513,4514],{"class":501,"line":557},[499,4515,517],{"emptyLinePlaceholder":516},[499,4517,4518,4520,4522,4524,4526,4528],{"class":501,"line":614},[499,4519,910],{"class":560},[499,4521,564],{"class":505},[499,4523,915],{"class":560},[499,4525,99],{"class":505},[499,4527,622],{"class":547},[499,4529,625],{"class":505},[499,4531,4532,4534,4536,4538,4540,4542,4544,4546,4548,4550,4552],{"class":501,"line":628},[499,4533,927],{"class":560},[499,4535,99],{"class":505},[499,4537,932],{"class":547},[499,4539,935],{"class":505},[499,4541,939],{"class":938},[499,4543,942],{"class":505},[499,4545,945],{"class":509},[499,4547,99],{"class":505},[499,4549,950],{"class":509},[499,4551,213],{"class":505},[499,4553,554],{"class":505},[499,4555,4556,4558,4560,4562,4564,4566,4568,4570,4572,4574,4576,4578,4580,4582],{"class":501,"line":664},[499,4557,960],{"class":560},[499,4559,99],{"class":505},[499,4561,965],{"class":547},[499,4563,575],{"class":505},[499,4565,970],{"class":658},[499,4567,587],{"class":505},[499,4569,975],{"class":505},[499,4571,978],{"class":938},[499,4573,942],{"class":505},[499,4575,945],{"class":509},[499,4577,99],{"class":505},[499,4579,987],{"class":509},[499,4581,213],{"class":505},[499,4583,554],{"class":505},[499,4585,4586,4588,4590,4592,4594,4596,4598,4600,4603,4606,4608,4610,4612,4614,4616,4618,4620,4622],{"class":501,"line":695},[499,4587,997],{"class":560},[499,4589,99],{"class":505},[499,4591,1002],{"class":547},[499,4593,575],{"class":505},[499,4595,578],{"class":505},[499,4597,4271],{"class":581},[499,4599,578],{"class":505},[499,4601,4602],{"class":505}," +",[499,4604,4605],{"class":560}," time",[499,4607,99],{"class":505},[499,4609,4283],{"class":547},[499,4611,4286],{"class":505},[499,4613,4289],{"class":547},[499,4615,575],{"class":505},[499,4617,4278],{"class":560},[499,4619,99],{"class":505},[499,4621,4298],{"class":560},[499,4623,3612],{"class":505},[499,4625,4626],{"class":501,"line":716},[499,4627,1044],{"class":505},[499,4629,4630],{"class":501,"line":807},[499,4631,1050],{"class":505},[499,4633,4634],{"class":501,"line":818},[499,4635,517],{"emptyLinePlaceholder":516},[499,4637,4638,4640,4642,4644,4646,4648,4650,4652,4654,4656,4658,4660,4662,4664],{"class":501,"line":837},[499,4639,4309],{"class":560},[499,4641,99],{"class":505},[499,4643,3500],{"class":547},[499,4645,4286],{"class":505},[499,4647,4318],{"class":547},[499,4649,575],{"class":505},[499,4651,578],{"class":505},[499,4653,4325],{"class":581},[499,4655,578],{"class":505},[499,4657,587],{"class":505},[499,4659,527],{"class":505},[499,4661,4121],{"class":581},[499,4663,578],{"class":505},[499,4665,611],{"class":505},[499,4667,4668,4670,4672,4674,4676,4678,4681,4683,4685,4687,4689,4691,4693],{"class":501,"line":860},[499,4669,1083],{"class":523},[499,4671,1066],{"class":560},[499,4673,564],{"class":505},[499,4675,915],{"class":560},[499,4677,99],{"class":505},[499,4679,4680],{"class":547},"Render",[499,4682,575],{"class":505},[499,4684,4143],{"class":560},[499,4686,1155],{"class":505},[499,4688,1066],{"class":560},[499,4690,1088],{"class":505},[499,4692,1091],{"class":505},[499,4694,554],{"class":505},[499,4696,4697,4699,4701,4703,4705,4707,4709,4711,4713,4715,4717,4719],{"class":501,"line":896},[499,4698,4371],{"class":560},[499,4700,99],{"class":505},[499,4702,4376],{"class":547},[499,4704,575],{"class":505},[499,4706,4143],{"class":560},[499,4708,587],{"class":505},[499,4710,4385],{"class":560},[499,4712,99],{"class":505},[499,4714,4376],{"class":547},[499,4716,3599],{"class":505},[499,4718,4394],{"class":658},[499,4720,611],{"class":505},[499,4722,4723],{"class":501,"line":902},[499,4724,1117],{"class":505},[499,4726,4727],{"class":501,"line":907},[499,4728,719],{"class":505},[18,4730,4731,4732,4734,4735,4738,4739,4741,4742,99],{},"Misma forma. ",[26,4733,433],{}," transmite el PDF directamente a la respuesta. Si quieres fijar ",[26,4736,4737],{},"Content-Length",", llama primero a ",[26,4740,1203],{}," para obtener el slice de bytes y aplícale ",[26,4743,4744],{},"len()",[13,4746,4748],{"id":4747},"cómo-de-rápido-es-suficientemente-rápido","¿Cómo de rápido es \"suficientemente rápido\"?",[18,4750,4751,4752,4754,4755,4758],{},"gpdf es aproximadamente ",[21,4753,36],{}," en las cargas que la gente ejecuta de verdad. Los números siguientes vienen de ",[26,4756,4757],{},"_benchmark/benchmark_test.go"," en un Apple M1 con Go 1.25.",[155,4760,4761,4778],{},[158,4762,4763],{},[161,4764,4765,4768,4770,4772,4775],{},[164,4766,4767],{},"Benchmark",[164,4769,23],{},[164,4771,169],{},[164,4773,4774],{},"gopdf",[164,4776,4777],{},"Maroto v2",[173,4779,4780,4799,4818,4836],{},[161,4781,4782,4785,4790,4793,4796],{},[178,4783,4784],{},"Página única",[178,4786,4787],{},[21,4788,4789],{},"13 µs",[178,4791,4792],{},"132 µs",[178,4794,4795],{},"423 µs",[178,4797,4798],{},"237 µs",[161,4800,4801,4804,4809,4812,4815],{},[178,4802,4803],{},"Tabla 4×10",[178,4805,4806],{},[21,4807,4808],{},"108 µs",[178,4810,4811],{},"241 µs",[178,4813,4814],{},"835 µs",[178,4816,4817],{},"8,6 ms",[161,4819,4820,4823,4828,4831,4833],{},[178,4821,4822],{},"Documento de 100 pág.",[178,4824,4825],{},[21,4826,4827],{},"683 µs",[178,4829,4830],{},"11,7 ms",[178,4832,4817],{},[178,4834,4835],{},"19,8 ms",[161,4837,4838,4841,4846,4849,4852],{},[178,4839,4840],{},"Factura CJK compleja",[178,4842,4843],{},[21,4844,4845],{},"133 µs",[178,4847,4848],{},"254 µs",[178,4850,4851],{},"997 µs",[178,4853,4854],{},"10,4 ms",[18,4856,4857],{},"No son sintéticos — el benchmark de tabla es una de líneas de factura de 4 columnas por 10 filas; el de 100 páginas es un informe paginado con cabecera repetida y números de página. La forma coincide con lo que hace el código real.",[18,4859,4860],{},"Una nota sobre lo que significan. A 13 µs por página única, un solo núcleo produce ~75.000 PDFs \"hello world\" por segundo. A 108 µs por página con tabla, ~9.000 facturas por segundo. El punto no es presumir — es que puedes dejar de pensar si hay que cachear o meter la generación de PDFs en una cola asíncrona. Para la mayoría de las cargas, generar en la misma vía de la petición está bien.",[13,4862,4864],{"id":4863},"lo-que-pierdes-al-migrar","Lo que pierdes al migrar",[18,4866,4867],{},"Nada de esta guía vale si oculta huecos reales. Esto es lo que gpdf no hace y gofpdf sí:",[4869,4870,4871,4880,4897,4903],"ul",{},[117,4872,4873,206,4876,4879],{},[21,4874,4875],{},"Líneas en ángulos arbitrarios, curvas Bézier y caminos complejos.",[26,4877,4878],{},"c.Line()"," dibuja una línea horizontal que cruza una columna. Si estás produciendo dibujos técnicos o gráficos con geometría propia, gpdf aún no llega. (Gráficos prerrenderizados como imágenes: sin problema.)",[117,4881,4882,4887,4888,4890,4891,4893,4894,4896],{},[21,4883,4884,4886],{},[26,4885,32],{}," y trabajo con cursor absoluto."," Puedes posicionar absoluto con ",[26,4889,353],{},", pero si tu código existente son 2.000 líneas de ",[26,4892,32],{}," seguidas de ",[26,4895,671],{},", la migración es más bien una reescritura. La contrapartida es que el código reescrito suele tener la mitad de tamaño.",[117,4898,4899,4902],{},[21,4900,4901],{},"Campos de formulario (AcroForm)."," gpdf todavía no genera campos rellenables. Si tus PDFs son plantillas que los usuarios rellenan en un visor, quédate — por ahora — con una biblioteca que soporte AcroForm.",[117,4904,4905,4908],{},[21,4906,4907],{},"Anotaciones y marcadores."," Soporte básico de outline sí, anotaciones ricas no.",[18,4910,4911],{},"Si nada de esto te afecta, la migración es directa. Si te afecta, abre un issue — la hoja de ruta se mueve por lo que pide la gente.",[13,4913,4915],{"id":4914},"faq","FAQ",[18,4917,4918,4921],{},[21,4919,4920],{},"¿gpdf es un fork de gofpdf?","\nNo. gpdf es una reimplementación limpia. El trabajo de formato de cable PDF, el motor de layout, el subsetter de TrueType — todo escrito desde cero en Go puro. No comparte linaje con gofpdf ni sus forks. Tiene que ser reescritura limpia porque la arquitectura de gofpdf se construyó en torno a un único cursor mutable; no puedes sacar una cuadrícula declarativa de ahí sin romper todos los sitios de llamada.",[18,4923,4924,4927,4928,4931,4932,4935,4936,4939,4940,4943],{},[21,4925,4926],{},"¿gpdf tiene dependencias externas?","\nLa biblioteca core tiene cero. Ejecuta ",[26,4929,4930],{},"go mod graph | grep gpdf"," tras ",[26,4933,4934],{},"go get github.com/gpdf-dev/gpdf"," y verás una sola línea. El complemento ",[26,4937,4938],{},"gpdf-pro"," (HTML→PDF, cifrado AES, firmas, PDF/A) sí trae ",[26,4941,4942],{},"golang.org/x/net"," para parsear HTML, pero es opt-in y no hace falta para migrar.",[18,4945,4946,4949,4950,4953],{},[21,4947,4948],{},"¿Y CGO? gofpdf era CGO-free, ¿qué pasa con gpdf?","\nIgual. Go puro, sin CGO. Haz ",[26,4951,4952],{},"GOOS=linux GOARCH=arm64 go build"," y despliega un binario estático. Eso importa para imágenes distroless y Alpine, donde arrastrar una toolchain CGO te duplica el tamaño del contenedor.",[18,4955,4956,4962,4963,4965],{},[21,4957,4958,4959,4961],{},"Mi código gofpdf existente usa ",[26,4960,32],{}," para posicionamiento absoluto en todas partes. ¿Puedo migrar sin reescribir?","\nPuedes envolver ",[26,4964,353],{}," y tener algo que se le parezca. Pero si tu código está estructurado alrededor de la manipulación de cursor, el modelo del motor de layout es un cambio mental, no sintáctico. La mayoría de los equipos descubre que la reescritura es más corta que el original.",[18,4967,4968,4971],{},[21,4969,4970],{},"¿Y si go-pdf/fpdf se desarchiva?","\nEntonces tienes una opción más. La apuesta detrás de gpdf no es que gofpdf vaya a quedarse archivado para siempre — es que la arquitectura (basada en cursor, fuentes de un byte, sin CJK nativo) es un callejón sin salida independientemente de quién la mantenga. Generar PDFs en 2026 se parece más a montar una página web que a conducir un plotter, y la API debería reflejarlo.",[13,4973,4975],{"id":4974},"probar-gpdf","Probar gpdf",[18,4977,4978],{},"gpdf es una biblioteca Go para generar PDFs. Licencia MIT, cero dependencias externas, soporte CJK nativo.",[490,4980,4984],{"className":4981,"code":4982,"language":4983,"meta":495,"style":495},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","go get github.com/gpdf-dev/gpdf\n","bash",[26,4985,4986],{"__ignoreMap":495},[499,4987,4988,4990,4993],{"class":501,"line":502},[499,4989,494],{"class":509},[499,4991,4992],{"class":581}," get",[499,4994,4995],{"class":581}," github.com/gpdf-dev/gpdf\n",[18,4997,4998,5005,5006],{},[4999,5000,5004],"a",{"href":5001,"rel":5002},"https://github.com/gpdf-dev/gpdf",[5003],"nofollow","⭐ Star en GitHub"," · ",[4999,5007,5010],{"href":5008,"rel":5009},"https://gpdf.dev/es/docs/quickstart",[5003],"Leer la documentación",[13,5012,5014],{"id":5013},"lecturas-siguientes","Lecturas siguientes",[4869,5016,5017,5023,5028],{},[117,5018,5019,5020],{},"¿Cómo funciona la cuadrícula de 12 columnas en gpdf? ",[83,5021,5022],{},"(próximamente)",[117,5024,5025,5026],{},"¿Cómo embebo una fuente japonesa en gpdf? ",[83,5027,5022],{},[117,5029,5030,5034,5035],{},[4999,5031,5033],{"href":5008,"rel":5032},[5003],"Quickstart"," — setup en cinco minutos, incluyendo ",[26,5036,5037],{},"go.mod",[5039,5040,5041],"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":495,"searchDepth":513,"depth":513,"links":5043},[5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057],{"id":15,"depth":513,"text":16},{"id":71,"depth":513,"text":72},{"id":102,"depth":513,"text":103},{"id":149,"depth":513,"text":150},{"id":479,"depth":513,"text":480},{"id":1215,"depth":513,"text":1216},{"id":2394,"depth":513,"text":2395},{"id":3057,"depth":513,"text":3058},{"id":4107,"depth":513,"text":4108},{"id":4747,"depth":513,"text":4748},{"id":4863,"depth":513,"text":4864},{"id":4914,"depth":513,"text":4915},{"id":4974,"depth":513,"text":4975},{"id":5013,"depth":513,"text":5014},"2026-04-14","jung-kurt/gofpdf fue archivado en 2021 y go-pdf/fpdf en 2025. Guía para migrar a gpdf — Go puro, cero dependencias, soporte CJK nativo.",false,"md",{"name":5063,"totalTime":5064,"tools":5065,"steps":5067},"Migrar un proyecto Go de gofpdf a gpdf","PT30M",[5066],"Go 1.22+",[5068,5071,5074,5077,5080,5083],{"name":5069,"text":5070},"Reemplazar la ruta de import","Cambia github.com/jung-kurt/gofpdf (archivado en 2021) y github.com/go-pdf/fpdf (archivado en 2025) por github.com/gpdf-dev/gpdf, github.com/gpdf-dev/gpdf/document y github.com/gpdf-dev/gpdf/template.",{"name":5072,"text":5073},"Construir el documento con builders en lugar de cursores","Llama a gpdf.NewDocument con WithPageSize, WithMargins y WithFont. En vez de mover un cursor con SetXY, agrega páginas con doc.AddPage() y describe el contenido con RowBuilder y ColBuilder.",{"name":5075,"text":5076},"Convertir Cell y MultiCell a Text declarativo","Reemplaza pdf.Cell y pdf.MultiCell por c.Text(...) dentro de una columna. El texto se ajusta automáticamente al borde de la columna, por lo que el flag final de MultiCell desaparece. El tamaño de fuente, el peso y el color se pasan como opciones per-text.",{"name":5078,"text":5079},"Registrar fuentes CJK mediante WithFont","Para texto en chino, japonés o coreano, reemplaza pdf.AddUTF8Font por gpdf.WithFont(name, ttfBytes) en la construcción del documento. Ya no hace falta gestionar rutas TTF ni el flag UTF-8: el subset embedding ocurre automáticamente.",{"name":5081,"text":5082},"Reescribir las tablas con filas y columnas","Elimina los bucles anidados de Cell con anchos de columna manuales. Dentro de un AutoRow, usa row.Col(n, fn) para construir filas de tabla; la grilla de 12 columnas calcula los anchos y maneja los saltos de página.",{"name":5084,"text":5085},"Cambiar la llamada de salida","Reemplaza pdf.OutputFileAndClose(path) por doc.Generate() seguido de os.WriteFile(path, data, 0o644), o usa doc.Render(w) para escribir directamente en un io.Writer.",null,{},"/es/blog/gofpdf-migration",{"title":5,"description":5059},"es/blog/001.gofpdf-migration",[5092,5093,5094],"migration","comparison","tutorial","4frvNEbkeWYLCnJqhNF7kZQGnU7O-XtZW4CL5cczWBQ",1776529274344]