Written by , is a statically typed, compiled programming language designed by Google. It combines the performance and security benefits of a statically typed language with the ease of use typically associated with dynamically typed languages.
Due to its concurrency and multithreading mechanism, and a great standard library, Go is a popular choice for a wide range of applications, including web development, network programming, and systems programming.
PDF generation is an important task that is required for various types of applications. Efficiently generating PDFs at scale can be a complex task. However, Go, being known for its performance and efficiency, can be a good choice for generating PDFs in high-volume scenarios.
However, writing your own PDF generator can be a complex job to achieve. This is where .
The grid system with rows and columns makes layout management easier. It also supports automatic page breaks for handling content overflow. You also get built-in support for text, images, barcodes, QR codes, signatures, and much more.
I’m going to write about how you can create dynamic PDFs in Golang with the help of Maroto.
Why do we need PDF generation?
PDF generation capabilities can be extremely valuable for many types of projects and applications.
- Invoicing systems — automatically generating and sending PDF invoices to clients can ensure consistency in formatting and allow easy customization for invoice templates
- Reporting tools — PDF generation is crucial for creating detailed reports for business analytics, financial statements, or project status updates
- Ticketing systems — generating PDF tickets is essential for travel bookings, event admissions, or movie show confirmations
- Label creation — dynamically generating labels for shipping, product labelling, or organizational purposes ensures that the right information is presented clearly and accurately
- Certification generation — automatically creating certificates for course completions, awards, or certifications allows for easy customization and personalization of each certificate
- Contract management — generating legal documents or contracts with dynamic content based on specific terms or conditions streamlines the process of creating accurate and personalized agreements
You can imagine other use cases and see why automating PDFs ensure consistency and provide a professional-looking format.
What to know before using Maroto in Golang
Before moving forward, please make sure you got the following down:
- A basic understanding of Go
- Go installed on your machine, preferably the latest version, 1.22.2 at the time of writing
- Your preferred IDE or text editor — I recommend Visual Studio
- Go extension for your IDE if available
If you need to familiarize yourself with Go, you can
Generating PDFs with Maroto
To get started, let’s first discuss a few core concepts that play a crucial role in generating PDFs with Maroto.
Row
Defined by a height, a Row represents a horizontal section of the document. It can contain multiple columns (Col). The New function initializes a Row with a specified height.
Col
A Col represents a vertical section within a Row and can contain various components like text, images, QR codes, or barcodes. Columns are flexible in terms of content and size. The New function for Col can create a column with a specific size or a maximum size if no size is provided. The Add method allows adding components to a column.
Component
This is an interface that various document elements implement. Elements such as text, images, QR codes, and barcodes are considered components. They can be added to columns to build up the document content. Now let’s initiate a Go project.
Initializing a new Go project and installing dependencies
First, open up your favorite code editor, and open the folder in the editor where you’ll be saving all your code related to the project.
Now open a terminal window, and locate the project location, and run the following command:
go mod init github.com/USERNAME/PROJECT_NAME
In the command above, replace
The ticket contains three basic sections: header, body, and footer.
The header contains a logo, name and address of an imaginary company called Showbees Ticketing.
The body contains all the necessary tickets like the name of the show, language, date, venue, number of tickets, etc.. The body also contains a QR code and a barcode just to demonstrate how these can be implemented in your PDF.
The footer is very basic and contains a single text.
Let’s start by creating a .
Now, let’s create the header.
Creating a header
To create a header, we’ll be creating a new function. The function will take a parameter of type Company and will return a core.Row. The header is pretty simple. Let’s check out the code first:
func getPageHeader(c Company) core.Row {
return row.New(16).Add(
image.NewFromFileCol(4, c.LogoLocation, props.Rect{
Center: false,
Percent: 100,
}),
col.New(2),
col.New(6).Add(
text.New(c.Name, props.Text{
Style: fontstyle.Bold,
Size: 10,
}),
text.New(c.Address, props.Text{
Top: 6,
Size: 10,
}),
),
)
}
The header consists of three columns: an image column, an empty column, and a column containing text components. Let’s look at the code step-by-step.
The first line row.New(16) creates a new row component with a height of 16. This row will serve as the container for the header columns.
To render the image, you’ll need to use the image.NewFromFileCol method. This function is available in the
Let’s move on and create the body of the PDF. This is the longest of the functions, but now that you understand the basics of how Maroto works, it should be a breeze.
Creating a body
Create a new function called getShowDetails which accepts a ticket struct and returns an array of core.Row interface. First, copy and paste the below code into your main.go function:
func getShowDetails(t Ticket) []core.Row {
rows := []core.Row{
row.New(30).Add(
image.NewFromFileCol(4, t.ShowPosterLocation, props.Rect{
Center: true,
Percent: 100,
}),
col.New(8).Add(
text.New(t.ShowName, props.Text{
Style: fontstyle.Bold,
Size: 10,
}),
text.New(t.Language, props.Text{
Top: 6,
Style: fontstyle.Normal,
Size: 8,
Color: &props.Color{Red: 95, Green: 95, Blue: 95},
}),
text.New(t.ShowTime, props.Text{
Top: 12,
Style: fontstyle.Bold,
Size: 10,
}),
text.New(t.ShowVenue, props.Text{
Top: 18,
Style: fontstyle.Normal,
Size: 8,
Color: &props.Color{Red: 95, Green: 95, Blue: 95},
}),
),
),
row.New(6),
row.New(1).Add(
line.NewCol(12, props.Line{
Thickness: 0.2,
Color: &props.Color{Red: 200, Green: 200, Blue: 200},
SizePercent: 100,
Style: linestyle.Dashed,
}),
),
row.New(3),
row.New(16).Add(
col.New(2).Add(
text.New(strconv.Itoa(t.TicketCount), props.Text{
Style: fontstyle.Bold,
Size: 24,
Align: align.Center,
}),
text.New("Tickets", props.Text{
Top: 12,
Style: fontstyle.Normal,
Size: 8,
Color: &props.Color{Red: 95, Green: 95, Blue: 95},
Align: align.Center,
}),
),
col.New(2),
col.New(8).Add(
text.New(t.Screen, props.Text{
Size: 8,
Color: &props.Color{Red: 95, Green: 95, Blue: 95},
}),
text.New(t.SeatNumber, props.Text{
Top: 6,
Style: fontstyle.Bold,
Size: 14,
}),
),
),
row.New(3),
row.New(1).Add(
line.NewCol(12, props.Line{
Thickness: 0.2,
Color: &props.Color{Red: 200, Green: 200, Blue: 200},
SizePercent: 100,
Style: linestyle.Dashed,
}),
),
row.New(6),
row.New(20).Add(
code.NewQrCol(12,
fmt.Sprintf("%v\n%v\n%v\n%v", t.ID, t.ShowName, t.ShowTime, t.ShowVenue),
props.Rect{
Center: true,
Percent: 100,
},
),
),
row.New(10).Add(
col.New(12).Add(text.New(fmt.Sprintf("Booking ID: %v", t.ID), props.Text{
Style: fontstyle.Normal,
Size: 8,
Align: align.Center,
Top: 2,
})),
),
row.New(1).Add(
line.NewCol(12, props.Line{
Thickness: 0.2,
Color: &props.Color{Red: 200, Green: 200, Blue: 200},
SizePercent: 100,
Style: linestyle.Solid,
}),
),
row.New(3),
row.New(10).Add(
code.NewBarCol(12, strconv.Itoa(t.ID),
props.Barcode{
Center: true,
Percent: 100,
},
),
),
}
return rows
}
The code starts by initializing a new variable called rows, which consists of all the rows that will be returned from the function.
The rows slice starts by initializing a first row of height 30. In this row, an image is first added to the column which takes a third of the available area. The t.ShowPosterLocation is rendered here, with a few properties like centre alignment and size in percentage.
In the remaining 2/3rd space, a new column is added, which renders the show name, show language and the show time. Each of the text has a different size, top position, and color. For defining the colors, the props.Color struct is used, where the value of red, green, and blue is defined.
The next row is added to add a blank space in the PDF. After the blank space, a new line is added to the rows slice. A new line can be added using the line module available in the Maroto package.
The line.NewCol function takes two arguments, one being the area to be taken, and another one for defining the properties of the line. In this case, the line takes the complete width, and different properties like the thickness, color, and size are defined. For the style, a dashed line is added.
After adding the line, another empty row is added, and after the empty row, the ticket count, screen name, and seat number are added.
Similar to the other columns, different props for the text are added for enhancing the look of the document. To display the ticket count, you must have noticed that we are using the strconv package to convert the integer type to string because the .
The complete code for the article is available in .
Get set up with LogRocket's modern error tracking in minutes:
- Visit ↗ Original-Artikel auf dev.to lesenVollständiger Original-BerichtAusführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
SOCIAL SHARE CARD GENERATOR