Godoc and Pkgsite: How to Turn Your Code into Documents
These tools are designed to transform these comments into user-friendly HTML documentation pages.
I’ve often navigated the choices between different tools for creating documentation and 2 noteworthy ones are Godoc and Pkgsite.
These tools are designed to transform these comments into user-friendly HTML documentation pages.
“So… godoc or pkgsite?”
While Godoc is technically deprecated, many still prefer it for its straightforward approach. Pkgsite is more modern but can feel a bit more complex.
Regardless of the choice between Godoc and Pkgsite, the underlying principle remains consistent: the importance of well-written, formatted comments in our code.
What is Godoc/ pkgsite
Godoc/ pkgsite is a tool for Go dev to create and maintain code documentation, it basically pulls comments directly from our code and converts them into static HTML documentation pages.
Simplicity in documentation: Both tools are built with simplicity in mind and this is not only makes writing and maintaining documentation easier but also encourages more effective documentation practices.
Close ties with our code: Since these tools pull comments directly from the code, the documentation stays in sync with code updates (while comments can be outdated “sometimes”).
Ease of use: With godoc, especially, you don’t need complex syntax or additional tools, just regular comments in the code suffice.
While godoc is deprecated, its simplicity still wins over some developers compared to pkgsite.
Example
Let’s look at a practical example to see how this works:
// Package pet provides structures and functions for pet management.
package pet
// Pet represents a pet with a name, age, and species.
type Pet struct {
Name string
Age int
Species string
}
From this code, both Godoc and Pkgsite will generate documentation for the pet
package.
The way they present this information might differ slightly, but the core content extracted from the comments remains the same.
godoc
pkgsite
In the Godoc version, you’d see a straightforward layout, focusing on the comments and structure definitions and pkgsite on the other hand, might offer a more polished look with additional navigational features.
Installation Guide
To set up your own Go documentation, use either the godoc or pkgsite tool.
Here’s how you can install them:
# godoc
go install golang.org/x/tools/cmd/godoc@latest
# pkgsite
go install golang.org/x/pkgsite/cmd/pkgsite@latest
Once installed, you can start hosting the documentation server on your local machine, run the following command in your Go code directory:
godoc
# godoc -http :6060
pkgsite
# pkgsite -http :8080
You can view the documentation by navigating to localhost:<default-port>.
With godoc, it automatically displays all packages found in your $GOPATH and $GOROOT.
Pkgsite however behaves differently, it only shows the documentation for packages in the current directory.
A quick note on pkgsite, if you encounter a message saying “This page is not supported by this datasource” or if the page seems to be loading indefinitely, it could be due to the naming of your package.
Pkgsite expects a dot “.” in the package name. A common workaround is to rename your package to something like “github.com/yourname/yourpackage”, which includes a dot and should resolve the issue.
What are doc-comments?
Doc comments are placed right before key components, this could be a package, constant, function, type, or variable.
If you name something with a capital letter (like a type or a function), it’s known as an “exported” item. It’s a standard practice to precede each of these exported items with a doc comment. This helps explain what the item does or what it’s for.
// Species defines a type for representing various pet species.
type Species string
// Predefined constants for different pet species.
const (
Dog Species = "dog" // Represents a dog species.
Cat Species = "cat" // Represents a cat species.
)
Go has a neat feature where it can extract these doc comments and turn them into documentation, it supports various formats, including paragraphs, headings, links, lists, and preformatted code blocks.
I’ll demonstrate these using pkgsite, though the result is similar with godoc.
One key thing to remember, Go’s gofmt tool automatically re-formats your doc-comments.
Paragraph
A paragraph in Go doc comments is a series of unindented, non-blank lines. There are a couple of nuances with gofmt to remember:
gofmt will collapse multiple blank lines between paragraphs into a single blank line.
It also converts sequences of backticks (``) into left double quotes (“) and single quotes (‘) into right double quotes (”), as long as they’re not part of a preformatted code block.
Original:
// This is a ``paragraph''.
//
//
// This is another paragraph.
After gofmt:
// This is a "paragraph".
//
// This is another paragraph.
The resulting documentation for this comment might look like this:
But if you don’t break the line with “//”, Go treats it as a single paragraph:
// This is a paragraph.
// This is not another paragraph
Heading
A heading is distinctly marked by a line that begins with a number sign (#), a space, and then the heading text.
To ensure it is correctly formatted, especially when surrounded by other text, it’s best to separate headings with blank lines:
// # This is heading
// A paragraph.
//
// # This is heading
// A paragraph.
//
// # This is heading
//
// Another paragraph.
In the resulting documentation, as shown here:
You can click on these headings to get hyperlinks directly to that section.
It’s important to note that Go doc comments don’t support sub-headings. So using “##” or “###” will result in standard paragraph text, not a lower-level heading.
Links
Go documentation supports two main types of links: standard links and doc links.
Standard Links: These are your typical web links. They follow the format “[Link Text]: URL” in an unindented line.
Doc Links: These are great for referencing other parts of your Go package, allow you to link to exported identifiers within your package or even external ones seamlessly.
Here’s an example showing both:
// Pet represents a pet with a name, age, and species.
// More details on species can be found at [Species].
// If you don't know what species is, read [Species Wikipedia].
//
// [Species Wikipedia]: https://en.wikipedia.org/wiki/Species
type Pet struct {
Name string
Age int
Species Species
}
// Species defines the type for pet species with predefined constants for Dog and Cat.
type Species string
const (
Dog Species = "dog"
Cat Species = "cat"
)
“[Species]” is a doc link, leading to the Species type on the same page, while “[Species Wikipedia]” is a standard link, directing to an external page.
To reference other packages, you might write:
// More details on species can be found at [fmt.Printf].
Unfortunately, in my experience with godoc, I’ve noticed that cross-package doc links don’t always work as expected. They tend to redirect to URLs like “http://localhost:8080/fmt#Printf" instead of the correct “http://localhost:8080/pkg/fmt/#Printf".
This issue doesn’t occur with pkgsite, where cross-package links function perfectly.
List
When it comes to lists in Go doc comments, there are two primary types you can use: unordered and ordered lists, both follow a simple format:
Unordered Lists: Begin these with a bullet symbol like *, +, -, or •.
Ordered Lists: Start each item with a number followed by a period. Previously, right parenthesis could also be used, but gofmt standardizes it to a period.
Here’s an example in a Go comment:
// Pet represents a pet with a name, age, and species.
// Important points to consider about age:
// 1. Age is always rounded down to the nearest full year.
// 3. Age should be updated annually.
//
// Supported species:
// - Dog: Represents canine pets.
// - Cat: Represents feline pets.
type Pet struct {
Name string // Name of the pet.
Age int // Age of the pet in years.
ID int // Unique identifier for the pet.
Species Species // Species of the pet.
}
A couple of things to note:
Even if the sequence numbers in an ordered list are out of order or incorrect, they still render correctly, so you have some flexibility.
Unordered lists use two spaces before the bullet symbol, while ordered lists use just one.
Preformatted code blocks
For displaying code snippets, preformatted code blocks are ideal.
The key difference between a code block and a regular paragraph is an additional space at the beginning of each line.
// Pet represents a pet with a name, age, and species.
//
// Hi, this is a code block
// with 2 spaces at the start of each line,
// while a paragraph only has 1 space.
type Pet struct {
Name string // Name of the pet.
Age int // Age of the pet in years.
ID int // Unique identifier for the pet.
Species Species // Species of the pet.
}
And…
You can’t start a doc comment with a code block right away and you need at least one paragraph before it. Otherwise, it’s treated as a normal paragraph.
As you may recall from my Swagger practical guide, this is the reason I start with a title, followed by a blank line, and then the Swagger annotations.
// getPetByID godoc
//
// @Summary Get a pet by ID
// @Tags pets
// @Accept json
// @Produce json
// @Param id path int true "Pet ID"
// @Success 200 {object} Pet "Single Pet data"
// @Router /pets/{id} [get]
func getPetByID(c echo.Context) error {
// Implement logic to return a pet by ID
return c.JSON(http.StatusOK, Pet{})
}
The Swagger annotations are correctly interpreted as a code block, providing a clear and well-structured documentation for the API endpoints.