Go(lang) back to basics

Golang, which first appeared in 2009 , is fast becoming a server-side powerhouse with a simple and neat approach to language syntax and a very strong library. Language native concurrency support , which seems to be a common feature among newer breed of languages , is what makes the language even more relevant in an era of distributed, large scale data systems. Backed by Google and a phenomenal community, Golang is proliferating ata a staggering pace. Go is aimed to be a bridge between fast execution(C, C++) and rapid development(Python) with its concise syntax and well design language features.

In this article, I would like to document some of language basics , concepts and nuances as I discovered while learning Go. Let’s Go………


A sample program

Instead of starting off with dry data types etc I will have a sample program and from there will dive into the basics of Golang. We shall write a program to calculate and output number of words in a file.

package main
import(
"fmt"
"strings"
"io/ioutil"
"os"
)
func WordCounter(s string) int {
cnt:= len(strings.Fields(s))
return cnt
}
func main() {
filename := os.Args[1]
contents, err := ioutil.ReadFile(filename)
if(err != nil){
fmt.Println(err)
return
}
//if we are here , we did not get an error. go ahead using
//data in contents to compute the word count
contentstr := string(contents)
     var wcnt int
wcnt = WordCounter(contentstr)
fmt.Println("Number of Words in input file is", wcnt)
}

package defines an a kind of organizing files and program. The first line of a go program is package declaration which in this case is main. The name of package enables various other .go files access and use functions and fields defined in another file. Conventionally we name the package with name of directory where those files sit in. package main is different in that this informs build system that this particular package is to be built as an executable. main() function in main package is the entry point to our programs.

import enables reusability in Go. This is kind of #includes in C. We can specify what all packages we will be needing in import statement and GO system fetches only them. In above file we have asked for fmt,strings,os and ioutil from io. These implement formatted I/O, UTF-8 string manipulation functions, interface to operating system functionality and io utility functions respectively. In Go, we can’t just import packages without using them; they are compiler errors. This is done to reduce bloat in the final binary and is a neat way to ensure lean software.

WordCounter is a function that takes a string as input and returns an integer. Both string and int are inbuilt data types. And we start a function definition using func keyword. Yeah I get it, the declaration syntax is different when we compare to C++, Java etc. For now agree to it and lets go ahead. I will cover that in a separate article.

cnt := len(strings.Fields(s)) Here we are using := as shortcut to declare and initialize a variable. We could have explicitly declared using var as we do later in code in main function. len()is a built-in function that takes types like Array,Slice,String etc and returns the length. Argument to len() here is Fields function (implemented in strings package which we imported) which takes a string and returns a string slice of strings. We will explore slice in detail but for now assume slice is like a dynamic array. Fields splits the input string around whitespaces and returns slice of substrings. len() operates on this slice and returns us the number of substrings in the slice which is nothing but word count in the string. This value is returned to caller of WordCounter().

func main() is the lead actor of our fucntion. This is the entry point to our program execution. os.Args gives us access to command-line arguments. (os.Args[0] is executable path and rest from os.Args[1] are arguments). In first line of main function, we initialise a string filename with first argument to our program which is a filename whose word count we are interested in. On this filename, we perform read using ReadFile() function which returns a tuple ([]byte, error). if error is nil, we can go ahead and use contents of the file saved to byte slice. We convert this byte slice to a string and then pass it to WordCounter() which returns the word count.

fmt.Println is function to print a line similar to printf in C which outputs the word count of the file.

Build and Rrrrun

We save above file as mypgm.go and use go command to build as below:

go build mypgm.go

If all is well, this produces mypgm executable in same location which can be called as below:

./mypgm mypgm.go

I am using the go file as argument to my program. I got a nice print as expected giving me word count

“Number of Words in input file is 51”

Though seemingly very trivial, this program covers many basics of Golang to get us started. We can build our skillset from here.

Go command

As we saw above, go build <filename> builds the code and results in executable. But go tool has other uses too. I will briefly describe some below:

  • go run <filename>: This builds and runs the program in a single shot.
  • go fmt <filename>: This automatically formats Go source code. This coming within the language helps to have a standardized , non controversial formatting of code and helps to understand code easier across teams or even companies.
  • go vet <filename>: This reports suspicious constructs in code . Though not always accurate this is a very useful tool to use for some errors not caught by compiler.

One can see various commands using go by just typing go in shell. It is a good interface to handle and manage go source code

$GOROOT and $GOPATH

$GOROOT: is the location where go is installed. We need not specifically set GOROOT unless it is not installed in default location.

$GOPATH: This is where we want our source code and this is where go get command downloads remote source to. Set like export GOPATH = /path/to/gopath

Remote imports? Not really !

I have heard people say go imports packages from remote locations like on github or BitBucket right away with imports like below:

import "github.com/some_magician'sgithubcode"

But this will not work unless we have downloaded that sourcecode we are describing explicitly using go get command:

go get "github.com/somemagician'sgithubcode"

This will download the package to $GOPATH and now you can use import as above but it is imported locally and not from github anymore. Just to clear the fallacy.

Conclusion

We have seen Go’s way of working using a small piece of code and learnt how to build and run go code. We have parked things like slice to later discussion which obligates me to cover it in a separate article along with more language constructs like maps and arrays and Go’s type system which can be approximated to Go’s answer to object orientation.

Happy learning !