Channels ▼
RSS

Parallel

Getting Going with Go


Another Example—Two-Dimensional Slices

The bigdigits program described next reads a number entered on the command line (as a string), and outputs the same number onto the console using “big” digits. Back in the twentieth century, at sites where lots of users shared a high-speed line printer, it was common practice for each user's print job to be preceded by a cover page that showed some identifying details such as the username and the name of the file being printed, using this kind of technique.

I'll review the code in three parts: first the imports, then the static data, and then the processing. But right now, let's look at a sample run to get a feel for how it works:

$ ./bigdigits  290175493

Each digit is represented by a slice of strings, with all the digits together represented by a slice of slices of strings. Before looking at the data, here is how we could declare and initialize single-dimensional slices of strings and numbers:

longWeekend := []string{"Friday", "Saturday", "Sunday", "Monday"} 
var lowPrimes = []int{2, 3, 5, 7, 11, 13, 17, 19}

Slices have the form []Type, and if we want to initialize them we can immediately follow with a brace-delimited, comma-separated list of elements of the corresponding type. We could have used the same variable declaration syntax for both, but have used a longer form for the lowPrimes slice to show the syntactic difference and for a reason that will be explained in a moment. Since a slice's Type can itself be a slice type we can easily create multidimensional collections (slices of slices, etc.).

The bigdigits program needs to import only four packages.

import ( 
    "fmt" 
    "log"
    "os" 
    "path/filepath"
)

The fmt package provides functions for formatting text and for reading formatted text. The log package provides logging functions. The os package provides platform-independent operating-system variables and functions including the os.Args variable of type []string (slice of strings) that holds the command-line arguments. And the path package's filepath package provides functions for manipulating filenames and paths that work across platforms. Note that for packages that are logically inside other packages, we only specify the last component of their name (in this case filepath) when accessing them in our code.

For the bigdigits program we need two-dimensional data (a slice of slices of strings). Here is how we have created it, with the strings for digit 0 laid out to illustrate how a digit's strings correspond to rows in the output, and with the strings for digits 3 to 8 elided.

var bigDigits = [][]string{
   {"  000  ",
    " 0   0 ",
    "0     0",
    "0     0",
    "0     0",
     "0  0",
     " 000 "},
    {" 1 ", "11 ", " 1 ", " 1 ", " 1 ", " 1 ", "111"},
    {"222","2  2","  2","  2 ","2  ","2  ","22222"},
    // ... 3 to 8 ...
    {" 9999", "9  9", "9  9", " 9999", "  9", "  9", "  9"},
}

Variables declared outside of any function or method may not use the := operator, but we can get the same effect using the long declaration form (with keyword var) and the assignment operator (=) as we have done here for the bigDigits variable (and did earlier for the lowPrimes variable). We still don't need to specify bigDigits' type since Go can deduce that from the assignment.

We leave the bean counting to the Go compiler, so there is no need to specify the dimensions of the slice of slices. One of Go's many conveniences is its excellent support for composite literals using braces, so we don't have to declare a data variable in one place and populate it with data in another.

The main() function that reads the command line and uses the data to produce the output is only 20 lines.

func main() {
    if len(os.Args) == 1 {
        fmt.Printf("usage: %s <whole-number>\n", filepath.Base(os.Args[0]))
        os.Exit(1)
    }

    stringOfDigits := os.Args[1] 
    for row := range bigDigits[0] {
        line := "" 
        for column := range stringOfDigits {
            digit := stringOfDigits[column] - '0' 
            if 0 <= digit && digit <= 9 { 
                line += bigDigits[digit][row] + " "
            } else {
                log.Fatal("invalid whole number") 
            }
        }
        fmt.Println(line)
    }
}

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