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.


Getting Started