Introduction
In this post, you will learn how to perform core PDF document management operations in Go using Aspose.PDF FOSS: opening and saving documents, creating new PDFs, splitting a document into per-page files, merging multiple PDFs, extracting page ranges, and reading or writing document metadata. All operations are available without any native C or C++ dependencies.
The library is a Go module at github.com/aspose-pdf-foss/aspose-pdf-foss-for-go,
MIT licensed, and requires Go 1.24 or later. Install with
go get github.com/aspose-pdf-foss/aspose-pdf-foss-for-go.
This post covers the Document, Page, PageRange, and DocumentInfo types that form
the core document management surface.
Core Operations
Opening and Saving Documents
pdf.Open loads a PDF from disk and returns a *Document. OpenWithPassword does
the same for password-protected files. Document.Save writes the result back to a
file path. Document.WriteTo writes to an io.Writer for in-memory or network
scenarios.
// Open a standard PDF
doc, err := pdf.Open("input.pdf")
if err != nil {
panic(err)
}
// Open an encrypted PDF
protected, err := pdf.OpenWithPassword("locked.pdf", "userpassword")
if err != nil {
panic(err)
}
// Save to a new path
err = doc.Save("output.pdf")
fmt.Println(protected.PageCount())
Creating a New Document
pdf.NewDocument creates an empty *Document. Use AddBlankPageFromFormat to append a blank page with a standard paper size. PageFormat provides named format constants (PageFormatA4, PageFormatLetter, etc.).
doc := pdf.NewDocumentFromFormat(pdf.PageFormatA4)
doc.Save("new_document.pdf")
Splitting a Document
Document.Split divides a PDF into individual per-page *Document values. Each
returned document contains exactly one page and can be saved independently. This
is useful for splitting batch-generated reports or separating invoice pages.
doc, _ := pdf.Open("multi_page.pdf")
pages, err := doc.Split()
if err != nil {
panic(err)
}
for i, p := range pages {
filename := fmt.Sprintf("page_%03d.pdf", i+1)
if err := p.Save(filename); err != nil {
fmt.Printf("Failed to save page %d: %v\n", i+1, err)
}
}
fmt.Printf("Split into %d pages\n", len(pages))
Merging Multiple PDFs
Document.Append merges a second *Document into the receiver in-place, appending
all pages from the source. Call Append repeatedly to chain multiple documents before
a single Save. The source document is not modified.
base, _ := pdf.Open("report_intro.pdf")
section1, _ := pdf.Open("section1.pdf")
section2, _ := pdf.Open("section2.pdf")
appendix, _ := pdf.Open("appendix.pdf")
base.Append(section1)
base.Append(section2)
base.Append(appendix)
base.Save("complete_report.pdf")
Extracting a Page Range
PageRange represents an inclusive range (1-based, using From/To fields). Pass ranges to
Document.Extract to produce a new *Document containing only the selected
pages. This is useful for building per-chapter exports or redacted copies that
omit certain pages.
doc, _ := pdf.Open("long_report.pdf")
// Extract pages 3 through 7
subset, err := doc.Extract(pdf.PageRange{From: 3, To: 7})
if err != nil {
panic(err)
}
subset.Save("pages_3_to_7.pdf")
Reading and Writing Document Metadata
Document.Info returns a DocumentInfo struct exposing
Info dictionary fields: Title, Author, Subject, Keywords, Creator,
Producer, CreationDate, and ModDate. Modify the fields directly, then call
Document.SetInfo to write the updated struct back before calling Save.
doc, _ := pdf.Open("report.pdf")
info, _ := doc.Info()
// Read current values
fmt.Printf("Title: %s\nAuthor: %s\n", info.Title, info.Author)
// Update fields
info.Title = "Annual Report 2026"
info.Author = "Finance Team"
info.Keywords = "annual, report, finance, 2026"
doc.SetInfo(info)
doc.Save("report_updated.pdf")
Accessing Individual Pages
Document.Page(n) retrieves a *Page by 1-based index. Document.PageCount returns
the total number of pages. Pages expose geometry properties for reading page boxes and
size.
doc, _ := pdf.Open("document.pdf")
fmt.Printf("Page count: %d\n", doc.PageCount())
page, _ := doc.Page(1)
size, err := page.Size()
if err != nil {
panic(err)
}
fmt.Printf("Page 1 size: %.0f x %.0f pt\n", size.Width, size.Height)
Quick Start
Install the module with go get, then run the complete example below. The example opens
a source document, extracts its first three pages into a new document, updates the
DocumentInfo metadata fields, and saves the result to disk.
go get github.com/aspose-pdf-foss/aspose-pdf-foss-for-go
A complete example that opens a document, extracts pages 1–3, and saves the result with updated metadata:
package main
import (
"fmt"
pdf "github.com/aspose-pdf-foss/aspose-pdf-foss-for-go"
)
func main() {
// Open source document
src, err := pdf.Open("source.pdf")
if err != nil {
panic(err)
}
// Extract pages 1-3
subset, err := src.Extract(pdf.PageRange{From: 1, To: 3})
if err != nil {
panic(err)
}
// Update metadata
info, _ := subset.Info()
info.Title = "Pages 1-3 Extract"
info.Author = "Document Pipeline"
subset.SetInfo(info)
if err := subset.Save("extract_pages_1_3.pdf"); err != nil {
panic(err)
}
fmt.Printf("Saved %d pages\n", subset.PageCount())
}
Open Source and Licensing
Aspose.PDF FOSS for Go is released under the MIT license. There are no usage restrictions, no runtime fees, and no registration requirements. The source code is available at github.com/aspose-pdf-foss/aspose-pdf-foss-for-go.