La generación de documentos PDF es prácticamente una parte integral de la creación de informes. Es mucho más sencillo tener una plantilla HTML que simplemente se edita y en los lugares necesarios se insertan los datos necesarios.
En este artículo, he seleccionado las herramientas más populares (por estrellas en GitHub en el momento de escribir este artículo) para generar PDF a partir de HTML, DOCX y algunos otros formatos. Solo consideraremos aquellas que están implementadas directamente en Go O tienen wrappers sobre la API en Go.
La lista es la siguiente:
- https://github.com/go-pdf/fpdf (623 ⭐)
- https://github.com/SebastiaanKlippert/go-wkhtmltopdf (1.1K ⭐)
- https://github.com/gotenberg/gotenberg (9K ⭐)
FPDF
Empezaremos con la menos popular de mi lista: https://github.com/go-pdf/fpdf.
A pesar de su sencillez, esta biblioteca tiene la funcionalidad más extensa para crear documentos PDF, que incluye agregar y eliminar páginas, insertar imágenes/texto/gráficos, ajustar los colores del texto y el fondo, agregar fuentes externas, administrar encabezados y márgenes. Para mí, las funciones más inusuales resultaron ser el dibujo de curvas de Bézier, incluso las compuestas.
Por cierto, esto se ve más o menos así (el código para la creación se toma del repositorio original).
Destacaré los pros y los contras más importantes de esta herramienta a mi parecer.
Ventajas:
- Biblioteca ligera con una cantidad mínima de dependencias.
- Muy flexible en términos de configuración del documento PDF de salida.
- API simple e intuitiva.
Desventajas:
- No se pueden editar archivos PDF existentes. La biblioteca solo admite la creación de nuevos.
- No hay posibilidad de trabajar con metadatos. Este punto inicialmente no iba a incluirse en la lista de contras, llegó aquí gracias a que las siguientes herramientas incluyen soporte para dicha funcionalidad.
- La última actualización del repositorio fue hace más de un año. Es posible que el autor lo haya abandonado, ya que hay muchos problemas abiertos sin respuesta.
El código más simple para crear un PDF se ve así (para una mayor simplificación, ignoro el error al guardar):
package main
import "github.com/go-pdf/fpdf"
func main() {
pdf := fpdf.New(fpdf.OrientationPortrait, fpdf.UnitPoint, fpdf.PageSizeA4, "")
// Establecemos la fuente. Courier es una de las fuentes integradas en la biblioteca,
// las demás fuentes tendrán que agregarse usando el método AddFont().
pdf.SetFont("Courier", "", 12)
pdf.SetFontSize(22)
pdf.AddPage()
pdf.SetTextColor(0, 191, 155)
pdf.Cell(40, 10, "Hola, Mundo!")
_ = pdf.OutputFileAndClose("hola.pdf")
}
Obtenemos el documento generado.

go-wkhtmltopdf
Esta biblioteca es un wrapper sobre la herramienta wkhtmltopdf, que está diseñada para convertir HTML a PDF y funciona con el motor WebKit. Esto significa que para usar la biblioteca cliente, es necesario instalar wkhtmltopdf en la máquina.
Al enumerar las funciones, me basaré en las capacidades de wkhtmltopdf, ya que el wrapper, según la descripción, proporciona todas sus funciones.
wkhtmltopdf tiene una buena compatibilidad con los estándares modernos de HTML, CSS y JavaScript, lo que significa que puedes crear PDF dinámicos con elementos interactivos. Como ejemplo, escribiremos una simple generación de documentos por URL (sí, también puede hacerlo) e ignoraremos nuevamente todos los errores para simplificar el código:
package main
import "github.com/SebastiaanKlippert/go-wkhtmltopdf"
func main() {
// Creamos un generador y establecemos la orientación de la página.
generator, _ := wkhtmltopdf.NewPDFGenerator()
generator.Orientation.Set(wkhtmltopdf.OrientationLandscape)
// "Alimentamos" la página de Wikipedia.
generator.AddPage(wkhtmltopdf.NewPage("https://es.wikipedia.org/wiki/Lorem_ipsum"))
_ = generator.Create() // Creación del documento PDF y guardado en el búfer.
_ = generator.WriteFile("wkhtmltopdf.pdf") // Escritura en la ruta especificada en el disco.
}

Obtenemos un resultado idéntico al que vemos al ir a la URL https://es.wikipedia.org/wiki/Lorem_ipsum
. Todos los enlaces y estilos se conservaron correctamente. Veamos los pros y los contras.
Ventajas:
- Puede generar PDF a partir de una URL: «alimente» una URL de una página de Wikipedia y obtendrá un PDF con los estilos originales.
- Gran cantidad de opciones para ajustar la calidad del documento de salida.
- Puedes controlar todos los parámetros desde el código usando el wrapper para Go, sin necesidad de comprender profundamente el funcionamiento de wkhtmltopdf.
Desventajas:
- Usar el wrapper, lógicamente, no es posible sin instalar el binario wkhtmltopdf.
- La velocidad de procesamiento de archivos grandes o complejos se convierte en un cuello de botella, ya que esta operación consume muchos recursos.
- No siempre procesa correctamente los elementos JavaScript complejos y asincrónicos.
- Pueden surgir problemas con la instalación en un entorno de contenedores, ya que puede ser necesario instalar bibliotecas adicionales para wkhtmltopdf.
Gotenberg
La herramienta más popular de las enumeradas, en parte porque tiene la funcionalidad más extensa para trabajar con documentos PDF. Puede generar PDF no solo a partir de HTML (CSS + JavaScript), sino que también admite la generación a partir de DOCX/PPTX/XLS, Markdown.
Gotenberg contiene varios motores, los principales son Chromium y LibreOffice, pero también hay ExifTool, PDFtk, pdfcpu, QPDF, UNO.
Es una especie de «multiherramienta» para generar documentos PDF. Otro aspecto importante es su documentación excelentemente elaborada, y también se proporciona como una imagen de Docker, lo que simplifica al máximo su configuración e inicio en un entorno de contenedores.
Gotenberg tiene muchas bibliotecas cliente para diferentes lenguajes, las más populares se destacan en un repositorio especial. Aunque su API en sí misma es bastante simple, vale la pena considerar el uso de clientes para no implementar el procesamiento y la formación de contenido multipart, no seguir constantemente las actualizaciones y la adición de nuevas funciones que, si es necesario, tendrían que implementarse también en su lado.
Enumeraré las principales funciones de Gotenberg:
- Conversión de Markdown y HTML a PDF con soporte para CSS y JavaScript.
- Conversión de DOCX, PPTX y XLS a PDF (usa el módulo LibreOffice).
- Lectura y escritura de metadatos en PDF (módulo exiftool).
- Amplia gama de configuraciones para controlar el contenido del documento PDF generado.
- Posibilidad de crear capturas de pantalla del archivo generado en formatos PNG, JPEG y WebP (apareció en la versión 8).
- En la versión 8.15, la última hasta el momento, aparecieron nuevas funciones para dividir documentos PDF página por página, especificando un intervalo de omisión o un rango específico de páginas.
- Posibilidad de combinar varios documentos en uno.
Como desventajas, se pueden mencionar las siguientes:
- La dependencia de Docker complica la tarea de implementación fuera de un entorno de contenedores.
- Herramienta bastante pesada y que consume muchos recursos. Realizamos pruebas de carga en pods con límites CPU=1000MiB y RAM=1Gb, pero solo pudimos lograr el procesamiento de 4 solicitudes simultáneas, y Gotenberg ya se negaba a ejecutar las demás.
- No se pueden paralelizar las operaciones en Gotenberg, como el propio autor ha mencionado varias veces en las discusiones del repositorio. Esto solo se puede lograr agregando nuevas instancias con Gotenberg, ya que una instancia solo funciona con un motor Chromium y/o LibreOffice en ejecución.
Mostraré un pequeño ejemplo de generación de PDF a partir de HTML utilizando la biblioteca https://github.com/starwalkn/gotenberg-go-client. Es un fork del cliente original del autor, que lamentablemente dejó de mantener después de la versión 7.
package main
import (
"net/http"
"os"
"github.com/starwalkn/gotenberg-go-client/v8"
"github.com/starwalkn/gotenberg-go-client/v8/document"
"context"
)
func main() {
// Creamos un cliente para conectarse a la instancia Gotenberg en ejecución.
client, err := gotenberg.NewClient("localhost:3000", http.DefaultClient)
// Creamos un "documento": una abstracción sobre archivos o lectores.
index, err := document.FromPath("index.html", "/path/to/file")
// Creamos una solicitud para la conversión de HTML a PDF.
req := gotenberg.NewHTMLRequest(index)
// La función downloadFrom apareció en la versión 8.
// Permite descargar archivos de fuentes externas, por ejemplo, de su almacenamiento S3.
downloads := make(map[string]map[string]string)
downloads["http://my.style.css"] = nil
downloads["http://my.img.gif"] = map[string]string{"X-Header": "Foo"}
req.DownloadFrom(downloads)
// Gotenberg también permite establecer la autenticación básica.
req.UseBasicAuth("username", "password")
// Luego tenemos dos opciones.
// 1. Guardamos el archivo generado directamente en el disco en la ruta especificada.
err = client.Store(context.Background(), req, "path/to/store.pdf")
// 2. Obtenemos el documento generado en representación de bytes en el cuerpo de la respuesta.
resp, err := client.Send(context.Background(), req)
}
Cabe tener en cuenta que las funciones de descarga de varios archivos de fuentes externas y la autenticación básica no están disponibles en las versiones anteriores a la 7, así que no dudes en actualizar las imágenes.
Resumen
La elección de la herramienta siempre o casi siempre depende de tus necesidades. FPDF se puede usar para crear documentos «desde cero» y si no necesitas la funcionalidad adicional que ofrecen otras herramientas. La elección entre wkhtmltopdf y Gotenberg depende en gran medida del entorno en el que planeas ejecutarlos. Gotenberg es ideal para ejecutar en un entorno de contenedores, pero puede convertirse en un cuello de botella con un gran flujo de solicitudes. wkhtmltopdf, por otro lado, es más adecuado para trabajar fuera de un entorno de contenedores debido a la instalación y configuración más complejas de tu Dockerfile.
Espero que hayas encontrado algo nuevo en este artículo, o al menos hayas refrescado tus conocimientos sobre las herramientas existentes para trabajar con documentos PDF. Si olvidé alguna otra herramienta popular, estaré encantado de que la menciones en los comentarios.