Last time I talked a bit about Go, the relatively new systems programming language that Google is promoting. Of course, a systems programming language invites comparison to C and, in fact, Go is a lot like C with some extras thrown in.
There is a “Tiny Go” runtime for embedded use (and an extension to make it more useful; see http://code.google.com/p/tinygo/). However, I wanted to focus on the language and not the application to a particular board. So I decided to write a simple tool in two different ways to get a feel for how it felt to Go (if that’s the right phrase for it).
The program I decided to write converts simple Intel-style hex files into binary (either real binary, or just an ASCII dump of the bytes). I wanted to write in one using Go as sort of a “super C” (similar to how I treated C++ for the LCD library a few weeks ago) and then another time using Go features for binding methods to types.
You can find the first version online. The Go driver has a multitude of features. It can run a go program, compile it, run tools, or even pretty print (that is, format) your source files. So, for example, to run the program you might enter:
go run hex2bin.go –a input.hex –
The structure of the program is what you might expect if you’ve written something like this in C. There is a main function that parses the command-line arguments and opens necessary files. It calls the dofile
function to process a file.
The dofile
code is short and sweet because it simply picks lines out of the file and sends them to procline
, which is where all the work occurs.
You’ve probably used hex files before. It is a simple ASCII file. Each line starts with a colon, a length, an address, a record type, a bunch of bytes, and a checksum. The only record types the program processes is the normal data record and the EOF marker.
Since I don’t normally put my C braces on the same line (though I was a fan of KR, I wasn’t a fan of their brace style), it took me a bit to remember that I have to put them on the same line for Go. I also kept putting unnecessary (but legal) semicolons at the end of lines out of habit.
The code itself is unremarkable. The _ character stands in for arguments that Go insists you use, but you don’t care about. It takes a little getting used to not declaring all your variables as you do in C. Of course, you do declare them, but any assignment with a := (instead of just a plain =) gets declared automatically based on the type of the right hand side of the expression.
There are a few places in the code where I did what amounts to a cast. For example, the binary write expects a byte array, but I have a single byte. That’s easy:
tmp := […]byte{byte(byt)} w.Write(tmp[0:1])
Note the implicit declaration of tmp
(which is, here, a byte array). I convert byt
(the byte from the input file) to a byte (a built-in Go type) and use that to initialize an array. The [0:1] notation specifies a slice of the array. While it might look like this brings in two elements, in reality it is only one. The last number is one past the end, basically.
The same thing occurs when I use slices to pick out parts of the line:
add, err := strconv.ParseInt(s[n+5:n+7]+s[n+3:n+5], 16, 16)
Here, the ParseInt
function returns two values and there are several string slices involved. The n
variable is the offset in the string to the leading colon character, so n+5
is the fifth character of the hex record. Picking the string apart like this reverses the address bytes so that 0010 becomes 1000, the correct way to read an Intel hex file.
One thing I learned very quickly is that using a search engine and typing in a keyword and “go” is pretty useless because go is such a common word. I don’t know if it is on purpose, or a coincidence, but using golang
seems to work much better. To find the documentation for ParseInt
try using Google to search for:
golang strconv
or
golang parseint
The program works and it is pretty parallel to an equivalent C program. It does, of course, use some objects from the Go library such as strconv
and os
, but it doesn’t really create any types of its own. Next time I want to explore a more “Go-ified” version of the same program and see what the advantages are over this C-style version.