Channels ▼
RSS

Design

A Brief Tour of the Go Standard Library


The Go standard library includes a large number of packages that provide a wide range of functionality. The overview provided here is highly selective and very brief. The contents of the library are likely to continue to grow after this article is published, so it is best to look at the library APIs online or locally using godoc (in the Go distribution) to get the most up-to-date information and get a comprehensive overview of what is available in each package.

The exp (experimental) package is where packages that might potentially be added to the standard library begin life, so these packages should not be used unless you want to participate in their development (by testing, commenting, or submitting patches). The exp package is normally available when pulling Go from Google's Go source tree, but it may not be included in prebuilt packages. The other packages are OK to use, although at the time of this writing, some are still incomplete.

Archive and Compression Packages

Go can read and write tarballs and .zip files. The relevant packages are archive/tar and archive/zip; and for compressed tarballs, compress/gzip and compress/bzip2.

Other compression formats are also supported; for example, Lempel-Ziv-Welch (compress/lzw), which is used for TIFF images and PDF files.

Bytes and String-Related Packages

The bytes and strings packages have many functions in common, but the former operates on []byte values and the latter on string values. The strings package provides all the most useful utilities to find substrings, replace substrings, split strings, trim strings, and change case. The strconv package provides conversions from numbers and Booleans to strings and vice versa.

The fmt package provides a variety of extremely useful print and scan functions, which were shown in the first and second installments of this series.

The unicode package provides functions for determining character properties, such as whether a character is printable, or whether it is a digit. The unicode/utf8 and unicode/utf16 packages provide functions for decoding and encoding runes (that is, Unicode code points/characters).

The text/template and html/template packages can be used to create templates that can then be used to generate textual output (such as HTML), based on data that is fed into them. Here is a tiny and very simple example of the text/template package in use.

    type GiniIndex struct {
	Country string
	Index float64
    }
    gini := []GiniIndex{{"Japan", 54.7}, {"China", 55.0}, {"U.S.A.", 80.1}}
    giniTable := template.New("giniTable")
    giniTable.Parse(
	'<TABLE>' +
	    '{{range .}}' +
	    '{{printf "<TR><TD>%s</TD><TD>%.1f%%</TD></TR>"' +
	    '.Country .Index}}'+
	    '{{end}}' +
	    '</TABLE>')
    err := giniTable.Execute(os.Stdout, gini)

This outputs

    <TABLE>
    <TR><TD>Japan</TD><TD>54.7%</TD></TR>
    <TR><TD>China</TD><TD>55.0%</TD></TR>
    <TR><TD>U.S.A.</TD><TD>80.1%</TD></TR>
    </TABLE>

The template.New() function creates a new *template.Template with the given name. Template names are useful to identify templates that are, in effect, nested inside other templates. The template.Template.Parse() function parses a template (typically from an .html file), which is then ready for use. The template.Template.Execute() function executes the template sending the resultant output to the given io.Writer, and reading the data that should be used to populate the template from its second argument. In this example, I have output to os.Stdout and passed the gini slice of GiniIndex structs as the data. (I've have split the output over several lines to make it clearer.)

Inside a template, actions are enclosed in double braces ({{ and }}). The {{range}} … {{end}} action can be used to iterate over every item in a slice. Here, I have set each GiniIndex in the slice to the dot (.); that is, to be the current item. We can access a struct's exported fields using their names, preceded, of course, with the dot to signify the current item. The {{printf}} action works just like the fmt.Printf() function, but with spaces replacing the parentheses and argument-separating commas.

The text/template and html/template packages support a sophisticated templating language in their own right, with many actions, including iteration and conditional branching, support for variables and method calls, and much else besides. In addition, the html/template package is safe against code injection.

Collections Packages

Slices are the most efficient collection type provided by Go, but sometimes it is useful or necessary to use a more specialized collection type. For many situations, the built-in map type is sufficient, but the Go standard library also provides the container package, which contains various collection packages.

The container/heap package provides functions for manipulating a heap, where the heap must be a value of a custom type that satisfies the heap.Interface defined in the heap package. A heap (strictly speaking, a min-heap) maintains its values in an order such that the first element is always the smallest (or largest for a max-heap) — this is known as the heap property. The heap.Interface embeds the sort.Interface and adds Push() and Pop() methods.

It is easy to create a simple custom heap type that satisfies the heap.Interface. Here is an example of such a heap in use.

    ints := &IntHeap{5, 1, 6, 7, 9, 8, 2, 4}
    heap.Init(ints) // Heapify
    ints.Push(9) // IntHeap.Push() doesn't preserve the heap property
    ints.Push(7)
    ints.Push(3)
    heap.Init(ints) // Must reheapify after heap-breaking changes
    for ints.Len() > 0 {
	fmt.Printf("%v ", heap.Pop(ints))
    }
    fmt.Println() // prints: 1 2 3 4 5 6 7 7 8 9 9

Here is the complete custom heap implementation.

type IntHeap []int
    
    func (ints *IntHeap) Less(i, j int) bool {
	return (*ints)[i] < (*ints)[j]
    }
	
    func (ints *IntHeap) Swap(i, j int) {
	(*ints)[i], (*ints)[j] = (*ints)[j], (*ints)[i]
    }

    func (ints *IntHeap) Len() int {
	return len(*ints)
    }
    
    func (ints *IntHeap) Pop() interface{} {
	x := (*ints)[ints.Len()-1]
	*ints = (*ints)[:ints.Len()-1]
	return x
    }
    
    func (ints *IntHeap) Push(x interface{}) {
	*ints = append(*ints, x.(int))
    }

This implementation is sufficient for many situations. We could make the code slightly nicer to read by specifying the type as type IntHeap struct { ints []int }, since then we could refer to ints.ints rather than *ints inside the methods.

The container/list package provides a doubly linked list. Items added to the list are added as interface{} values. Items retrieved from the list have type list.Element, with the original value accessible as list.Element.Value.

    items := list.New()
    for _, x := range strings.Split("ABCDEFGH", "") {
	items.PushFront(x)
    }
    items.PushBack(9)
    for element := items.Front(); element != nil;
	element = element.Next() {
	switch value := element.Value.(type) {
	case string:
	    fmt.Printf("%s ", value)
	case int:
	    fmt.Printf("%d ", value)
	}
    }
    fmt.Println() // prints: H G F E D B A 9

In this example, we push eight single-letter strings onto the front of a new list and then push an int onto the end. We then iterate over the list's elements and print each element's value. We don't really need the type switch because we could have printed using fmt.Printf("%v ", element.Value), but if we weren't merely printing, we'd need the type switch if the list contained elements of different types. Of course, if all the elements had the same type, we could use a type assertion — for example, element.Value.(string) for string elements.

In addition to the methods shown in the aforementioned snippet, the list.List type provides many other methods, including Back(), Init() (to clear the list), InsertAfter(), InsertBefore(), Len(), MoveToBack(), MoveToFront(), PushBackList() (to push one list onto the end of another), and Remove().

The standard library also provides the container/ring package, which implements a circular list.

While all the collection types hold their data in memory, Go also has a database/sql package that provides a generic interface for SQL databases. To work with actual databases, separate database-specific driver packages must be installed. These, along with many other collection packages, are available from the Go Dashboard.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video