Golang Documenting Package Examples

Go has been gaining a lot of popularity recently. With a lot of the success stories centered on the performance gains switching from other languages. For me a lot of the smaller features, that shows an attention to detail, which makes it enjoyable to code in. These details are also what will help the Golang community grow as well. One of these details is the built in documentation into the language.

There is a built in go doc command with the language where you can view your package documentation locally by running an http server to serve your docs. GoDoc is the main hosting for open source packages that will build docs for your package by doing a go get and generating docs. Locally you can run go doc from your package to display the docs in your terminal.

$ cd $GOPATH/src/github.com/mtchavez/go-statsite/statsite
$ go doc
PACKAGE DOCUMENTATION

package statsite
    import "github.com/mtchavez/go-statsite/statsite"



VARIABLES

var MTypes []string = []string{
    "kv",
    "g",
    "ms",
    "c",
    "s",
}


TYPES

type Client struct {
    Conn net.Conn
    // contains filtered or unexported fields
}


func NewClient(addr string) (client *Client, err error)


func (c *Client) Emit(m Messenger) (bool, error)

func (c *Client) Emitter(msg string) (ok bool, err error)

Or you can view all the packages in your $GOSRC directory as well as the standard library code in your browser by running godoc -http=:6060. Then visit localhost:6060 in your browser. This looks the same as golang.org you may notice. Click on Packages and find the package you are looking for. This all comes built into the language itself.

If you have spent any time using go, browsed the standard library docs, used an open source go project you may have notice a Examples in docs. These examples are one of the details I mentioned that add to the language and help grow a community. Here is an example of the built in time package examples. The novel thing about this is it is just the built in examples from the Go source that get generated by go doc from the language itself. There is no extra documentation package or custom manages site.

So you have an open source project, or some internal go project, that you want to make life easier for others to pick up and understand. Lets write an example for them to understand how to use your package. Lets say you have a fibonacci number generator package. And you want to show someone how to use it with an example. Lets add a $GOPATH/src/fib directory with a fib.go main package with the following:

package fib

import (
  "fmt"
  "os"
  "strconv"
)

func fib(n int) int {
  if n < 2 {
    return n
  }
  return fib(n-1) + fib(n-2)
}

Since we’ll be expecting others to use our package we’ll want to test it works as well as document how to use it. With examples we can do both in one shot. In our same $GOPATH/src/fib directory create a fib_test.go file. Lets add our example test.

package fib

import (
  "fmt"
)

func Example() {
  var output int
  output = fib(10)
  fmt.Printf("Fibonacci of %v is %v\n", 10, output)
  output = fib(20)
  fmt.Printf("Fibonacci of %v is %v\n", 20, output)
  // Output:
  // Fibonnacci of 10 is 55
  // Fibonnacci of 20 is 6765
}

Now from your fib/ directory run go test and you should see some similar output:

$ go test
PASS
ok    fib 0.023s

This allowed us to both test our fibonacci package and show someone else an example how to use it. If the output changed or we broke our package our tests should fail as well.

$ go test
--- FAIL: Example (80.68us)
got:
Fibonacci of 10 is 55
Fibonacci of 20 is 6765
want:
Fibonacci of 10 is 55
Fibonacci of 20 is 55
FAIL
exit status 1
FAIL  fib 0.018s

Simple enough. What if you have a struct where you are calling a function off of and want to show how one would use the function. The principal is the same except we change our Example() function name in our test. If we change our fib.go to this:

package fib

import (
  "fmt"
  "os"
  "strconv"
)

type FibStruct struct {
  num    int
  result int
}

func fib(n int) int {
  if n < 2 {
    return n
  }
  return fib(n-1) + fib(n-2)
}

func (f *FibStruct) Calculate(num int) {
  f.num = num
  f.result = fib(num)
}

Then we can add an example on how to use our new Calculate() method in fib_test.go.

func ExampleFibStruct_Calculate() {
  f := FibStruct{}
  f.Calculate(10)
  fmt.Printf("Fibonacci of %v is %v\n", 10, f.result)

  f.Calculate(20)
  fmt.Printf("Fibonacci of %v is %v\n", 20, f.result)
  // Output:
  // Fibonacci of 10 is 55
  // Fibonacci of 20 is 6765
}

Running the tests again with go test should show everything passing. Last part to this is viewing your examples via go doc or on GoDoc. You can view this example at fib-go- example.