Packages: Core Packages - kyunghoj/golang GitHub Wiki

Errors

Go has a built-in type for errors that we have already seen (the error type). We can create our own errors by using the New function in the errors package:

package main

import "errors"

func main() {
    err := errors.New("error message")
}

Containers and Sort

In addition to lists and maps, Go has several more collections available underneath the container package. We'll take a look at the container/list package as an example.

List

package main

import ("fmt" ; "container/list")

func main() {
    var x list.List
    x.PushBack(1)
    x.PushBack(2)
    x.PushBack(3)

    for e := x.Front(); e != nil; e=e.Next() {
        fmt.Println(e.Value.(int))
    }
}

Sort

The sort package contains functions for sorting arbitrary data. There are several predefined sorting functions (for slices of ints and floats). Here's an example for how to sort your own data:

package main

import ("fmt" ; "sort")

type Person struct {
    Name string
    Age int
}

type ByName []Person
func (ps ByName) Len() int {
    return len(ps)
}
func (ps ByName) Less(i, j int) bool {
    return ps[i].Name < ps[j].Name
}
func (ps ByName) Swap(i, j int) {
    ps[i], ps[j] = ps[j], ps[i]
}

func main() {
    kids := []Person{
        {"Jill",9},
        {"Jack",10},
    }
    sort.Sort(ByName(kids))
    fmt.Println(kids)
}

Hashes and Cryptography

Here's an example using crc32:

package main

import (
    "fmt"
    "hash/crc32"
)

func main() {
    // create a hasher
    h := crc32.NewIEEE()
    // write our data to it
    h.Write([]byte("test"))
    // calculate the crc32 checksum
    v := h.Sum32()
    fmt.Println(v)
}

The crc32 hash object implements that Writer interface, so we can write bytes to it like any other Writer. Once we've written everything we want, we call Sum32() to return a uint32. A common use for crc32 is to compare two files.

package main

import (
    "fmt"
    "hash/crc32"
    "io/ioutil"
)

func getHash(filename string) (uint32, error) {
    // open the file
    f, err := os.Open(filename)
    if err != nil {
        return 0, err
    }
    // remember to always close opened files
    defer f.Close()

    // create a hasher
    h := crc32.NewIEEE()
    // copy the file into the hasher
    // - copy takes (dst, src) and returns (bytesWritten, error)
    _, err := io.Copy(h, f)
    // we don't care about how many bytes were written, but we do want to
    // handle the error
    if err != nil {
       return 0, err
    }
    return h.Sun32(), nil
}

func main() {
    h1, err := getHash("test1.txt")
    if err != nil {
        return
    }
    h2, err := getHash("test2.txt")
    if err != nil {
        return
    }
    fmt.Println(h1, h2, h1 == h2)
}

One common cryptographic hash function is known as SHA-1. Here's how it is used:

package main

import (
    "fmt"
    "crypto/sha1"
)

func main() {
    h := sha1.New()
    h.Write([]byte("test"))
    bs := h.Sum([]byte{})
    fmt.Println(bs)
}

sha1 computes a 160-bit hash. There is no native type to represent a 160-bit number, so we use a slice of 20 bytes instead.