Playing with Go (AKA golang)

golangTo installing Go on debian Linux:

sudo apt-get install golang

Check your version like this:

go version
> go version go1.3.3 linux/amd64

Using you favorite text editor (IDEs are for the weak), create a file with the .go extension. I’ll call mine gnosis.go. Code a minimal go program like this (from go’s Getting Started page):

package main

import "fmt"

func main() {
 fmt.Printf("hello, world\n")
 }

Compile it like this (run from the directory where you save the program):

go build

Finally, you can run it, like this:

./gnosis
> hello, world

I want to make it do something interesting, so I will start with a simple note taking app. First, the gnosis program must read the note from standard input, which by default is the keyboard.

package main

import "io/ioutil"
 import "fmt"
 import "os"

func main() {
    note, _ := ioutil.ReadAll(os.Stdin)

    fmt.Print(string(note))
 }

After compile and running it, I typed:

This is a note
Line 2 of the note
[Ctrl-D]

In response, the program printed:

This is a note
Line 2 of the note

Some interesting things to note: ioutil.ReadAll reads the entire contents of a file (in this case, the standard input), and returns the content as a (byte-array, error) ordered pair. Specifying the error be stored in ‘_’ rather than a named variable tells Go to throw it away. The string function is used to convert the byte array into a string of characters. Finally, I typed [Ctrl-D] because in Linux, that is the way to simulate the end of file from the keyboard.

I would like to have a time-stamp associated with each note. To do this, I imported “time” and added this code right before the previous call to fmt.Print:

import "time"

timestamp := time.Now().UTC().Format("2006-01-02T15:04:05.999999999")
 fmt.Print(timestamp + "\n")

Compiling and running the program now causes the time-stamp for the current time to be output in the format shown on a line before the text of the note. But this leaves one more problem: I want to remember what I wrote in my note, so instead of just printing it out, I store it in a structure and write it to a file:

package main

import "encoding/gob"
import "fmt"
import "io/ioutil"
import "os"
import "time"

type Note struct {
    Body    []byte
    Created time.Time
}

func main() {
    var note Note
    note.Body, _ = ioutil.ReadAll(os.Stdin)
    note.Created = time.Now().UTC()

    os.Mkdir("notes", 0700)
    name := note.Created.Format("notes/2006-01-02T15:04:05.999999999.gob")
    file, _ := os.OpenFile(name, os.O_CREATE, 0400)
    encoder := gob.NewEncoder(file)
    encoder.Encode(note)
    file.Close()
}

There’s a lot more going on here. First, I’ve created a type called Note that contains a body (what you type in) and a creation time. Next, I read the body, as before, and capture the creation time (without formatting it as a string this time).

NOTE: This took me a while to figure out: If the structure member’s names don’t begin with an upper case letter, they are not serialized. This is a very annoying quirk of the gob package that is not documented.

Next, I write the note out as a GOB, which can later be read back in and used. If there isn’t already a notes subdirectory, I create one. Then, I create a file whose name is the string formatted time-stamp of the note, followed by the extension .gob. Finally, I encode the note into the file as a GOB.

The GOB encodes the note in binary form. If you cat the file, it’s contents are quite unreadable, as parts of it are encoded. Try dumping it a command like the following one, with the time-stamp of the filename replaced with the one just created:

 od -c notes/2017-06-15T02\:14\:53.864365634.gob

You should see output like this:

od-gob

The first part of the file is a description of the type (Note) and its members (Body and Created). This is followed by the value, which includes the string you entered as the body and a binary representation of the time-stamp. This value can be decoded into a variable of type Note. I’ll discuss doing so in a future post.

Advertisements

About jimbelton

I'm a software developer, and a writer of both fiction and non-fiction, and I blog about movies, books, and philosophy. My interest in religious philosophy and the search for the truth inspires much of my writing.
This entry was posted in golang programming and tagged , , , , . Bookmark the permalink.

One Response to Playing with Go (AKA golang)

  1. Pingback: CLI, Directories, and Gob in Go | Programming with Jim

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s