Super-simple introduction highlighting how Go is giving C-superpower back to the modern web with syntactic twists of many lovable scripting languages.
Last week, after a month of exposing myself to Arduino/C++ and Javascript programming a Spark microcontroller and Socket.io web app for my recent IoT toy project, I have decided to kill my time trying out Go, a new language developed by Google, out of curiosity of discovering what all the buzz was all about. Apart from the necessary fuzzes you have to deal with static-typed languages like C and Java, after following some tips and tutorials online, my Go journey seemed to remind me of the joy I had when picking up Python.
I recommend a free e-book An Introduction to Programming in Go by Caleb Doxey, which is the easiest intro I found on the internet aimed for beginners. You can also download example codes and solution to problems in this book from my Github repo here.
Go or Golang is a statically-typed language with syntax loosely derived from that of C, with extra features such as garbage collection (like Java), type safety, and some dynamic-typing capabilities. developed at Google in 2007 by a bunch of clever people, Robert Griesemer, Rob Pike, and Ken Thompson. Go is a general-purpose programming language with focus on the web. What makes much of Go’s momentum is arguably its pitch on concurrency, asynchronosity (that of Node.js), speed (that of C), and of course the must-have in any web programming language these days—scalability.
Installing Go
Go is a compiled programming language that compiles so fast it feels like interpreted (Thus, don’t expect interactive shell or REPL mode). To install Go and its compiler (Gc), head over to http://www.golang.org and download the latest version in binary, then install it. You should end up with a directory structure similar to this:
$HOME
├── Go
├── bin
├── pkg
└── src
If you’re on Mac OSX or Unix, you will want to export a GOPATH environment variable to your Go’s directory, put these lines somewhere in your .bashrc or .bash_profile file.
In your terminal, type go to unveal several commands to try out (i.e. go version prints out your version of go installed.) From this point, you might want to create a directory under ~/go/src and keep your codes in there.
Hello Mars!
To spice up your experience, let’s begin with a “Hello Mars!” programming tradition. Create a file named hello_mars.go and write the code:
After saving the file, run with:
~$ go run hello_mars.go
You see, a very sweet thing you discover upfront is Go supports UTF-8 format out of the box, and that’s handy since the web is global. The above code prints out “Hello Mars!” in English, Chinese and Thai.
If you have programmed in Python, C and/or Java, you’ll notice the familiarities right away. Go main program consists roughly of three parts: package name, imported packages and main function. Like in C/C++, Go compiler always look for main() function to start from. Unlike in C, Go has no precompiler directives or included header files, and that’s what make it compiles fast.
Package and Import
Keyword package is a way to let Go knows what package you block of code is and how it can be imported. For instance, in a main.go program with the function named main, you should also name the package main. Inside the fmt package, the first line of code is package fmt and that lets you import the code using import “fmt”
Below is how the fmt code’s head looks like:
// fmt package
package fmtimport (
“strconv”
“unicode/utf8"
)
...
After importing a package, you can use the package’s exported names. Exported names (or public) in Go begin with a capital letter that signifies they can be used anywhere else. (Remember, capital letters mean grownups and ready to explore the outside world. lower cases mean toddlers which still belong in a crib of code)
package mainimport (“fmt” ; "math")func main() {
// use the exported method name
fmt.Println("Bambi is not a gopher")
// this will fail
p := math.pi
}
Go doesn’t require explicit semicolons `;` to end statements, but, like CoffeeScript, Go does have implicit invisible semicolons. Therefore, you can and will use semicolons where appropriate.
Types
Go types are more or less similar to C’s, but have simpler syntaxes that are easier to remember:
- uint8, uint16, uint32, uint64 are for unsigned integers of corresponding sizes
- int8, int16, int32, int64 are for signed integers of corresponding sizes
- byte and rune is equivalent to uint8 and uint32, respectively
- int, uint, uintPtr are machine-dependent, meaning the sizes are up to your computer’s architecture (i.e. 32- or 64-bit)
- float32 and float 64 for floating point numbers
- NaN for “Not-a-number” like 0/0
- complex64 and complex128 for complex numbers
- string for strings of text
- bool for booleans (true, false)
- struct and interface are special types that make the object-oriented side of Go, which we shall see later.
Your First Variables
Go has a rather unique way of declaring a variable that’s very different than C-style syntax. The type declaration is always on the right of the variable name. This left-to-right approach is there it is easier to read and make sense by us humans.
var name string
Above line reads “create a variable called name of type string”. Head to this blog for an enjoyable read on why.
Go infers type based on your assigned value, and declaring a variable even use keyword var just like JavaScript. For constants, use the keyword const. You can also assign multiple variables all at once doing this:
var (
a = 45
b = “Gophers ain't beavers”
c = 34.01
)
In fact, just FYI, you can also import several packages in the same way
import (
"fmt"
"net/http"
"math"
)
Loop (without an ‘s’)
This is one of Go’s features that is really refreshing. Go boldly chose for loop as the only one loop in its language. In C, you have three kinds of loops, all with different syntax and overlapping semantics. Go manages to have more expressive loop semantics, but simple and uniform syntax.
Also, one thing to note is Go has no pre- and post-increment expression. Developers of Go decided to just get rid of the confusing pre- and post-increment expressions in C. Therefore, a++ is a statement, and only suffix is allowed, thus you can’t do something like b := a++ or ++a.
There are special forms of for loop which are just awesome, and will be introduced appropriately when we talk about arrays, slices, and maps.
If and Switch
The above snippet loops through integer 1 to 10 and prints the string “even” for even values and “odd” for odd values. Note that if and for statements do not require parentheses. In fact, Go doesn’t even allow them in conditionals and loops.
Switch statement is simple enough, and has no different from C. The code below make use of Scanf() method of fmt package that prompts for the user’s input. It then prints the English string corresponding to the number received up to 5.
Arrays, Slices and Maps
Like Python, Go supports lists and maps. However, being statically-typed, each can only contain values of the same type.
An array is a numbered sequence of elements of a single type with a fixed length. To create an array, you do something like this:
var x [5]int // remember the type is always on the right
This creates an array of integers of length 5.
Arrays are mutable, meaning their values can be changed later. Below, we are creating an empty array x and assign 100 to the last member of x.
When you run the program with go run array.go the program will print out [0 0 0 0 100]. One thing you need to remember coming from other languages is that when you declare a variable of any type without assigning a value, you’re setting it to 0. This is a big convenience because like how you get undefined in JavaScript’s unassigned variables, it keeps your program from any runtime failure.
To loop through an array, we simply use for loop to do like in C/C++. This code will print out all the members of array arr.
Note that we used array literal to initiate an array and assign members on the spot. This can also be done on separate lines like this:
var arr = [10]int{
1, 21, 35, 4, 30,
6, 12, 9, 4, 10,
}
However, I’ve said there is a special form of for loop designed for list traversal exclusively, and here it is.
for i, v := range arr {}
i stands for the current position or index in arr, just like in the previous loop, while v is equivalent to arr[i]. It doesn’t matter what letters you use for the variables, when you’re using this form of loop, the first variable after the keyword for will be the index and the (optional) second variable after the comma will be the corresponding value. The array_loop.go can be rewritten this way:
We use `_` instead of i because Go won’t allow unused variables lying around and will complain about it, and underscore is (js-convenient) way of letting the compiler knows that it’s ok to throw the variable away.
This kind of for loop is exceptionally neat since figuring out when and where to stop in an array can be unnecessarily painful, and sometime you might not even care to know how many members a list have. Scripting languages such as Python and Ruby adopt this form of loop, and even JavaScript has recently introduced forEach() method that help applying a function to each member of an array.
Slices are similar to arrays, except the length isn’t fixed, although limited. You can think of slices as similar to vectors in C++ with limited length. A slice is associated with an array. We kind of allocate an array in the computer’s memory, then create and associate a slice to it. To create a slice, you simply create an empty-sized array:
var x []string
However, if you try to print the slice x, you will get nothing, not even zeroed list, because you have not initiate any length or capacity for it. To do so, you will use Go’s built-in function make():
var x= make([]string, length, capacity)
An optional argument capacity is the maximum capacity a slice can get to. As you can see, a slice is, well, a sliced array.
In fact, you can even create a slice using [ low : high ] statement, like splicing a list in Python.
var creatures = [4]string{"Pokemon", "Furby", "Unicorn", "Gopher"}
var s1 = creatures[0:2] // [Pokemon Furby]
var s2 = creatures[:4] // [Pokemon Furby Unicorn Gopher]
var s3 = creatures[1:] // [Furby Unicorn Gopher]
var s4 = creatures[:] // [Pokemon Furby Unicorn Gopher]
var s5 = creatures[2:len(creatures)] // [Unicorn Gopher]
Go has two built-in functions to deal with slices—append and copy. They are simple enough for you to try on yourselves.
A map is a collection of key-value pairs, known in some other languages as an associative array, hash table or dictionary. Here is a map in Go:
var x map[string]int
We need a keyword map preceding the square brackets, and explicitly tell Go that the index or key is a string. Maps, like slices, need to be initialized by using make function. Maps are useful in storing structured general information.
This code will print out the following:
Gopher with the power of digging
Pokemon with the power of lightning
Unicorn with the power of flying
Furby with the power of nagging
F's name is Furby
G's color is blue
My experience picking up Go is like revisiting an ex-girlfriend, and realized she’s changed and made you think why you had broken up. Go is very versatile and had carved out all the nooks an crannies that has made a beauty like C++ a pain to date with. I have never used a statically-typed language for any web projects, but I am really going to.
In part 2, I’ll write about function, pointer, struct, method and interface, which are the more advanced but very interesting topics.