AK

Programming in Go

Aug 16 2020
Over the weekend, I have been writing a lot of Go code to automate some of the repetitive stuff I do at work, such as updating servers after grabbing the latest code from the trunk. This morning, I programmed for three hours straight from 5 to 8 am, and enjoyed every minute of it. 

The more Go I write, the more I like it. Every time I make some change and hit `go run`, the compilation and execution speed brings a smile. Its simplicity continues to amaze me. There are not many moving parts in Go. Once I learned the basic syntax, I could read and understand any Go code, written by anyone. I am afraid I can't say the same about C# and JavaScript/TypeScript, all of which I have been programming for over four years. In contrast, with every new release, they are all getting bloated, making the languages difficult to understand and reason about. 

It's not just about writing Go. It's also about what Go enables you to do. For a long time in my career, I stayed away from systems programming, thinking it was a complicated topic for which you need to have a deep understanding of pointer arithmetic and bit twiiddling. 

After browsing through a lot of Go code over the last couple of months, I am glad to find that's not the case. Of course, Go has pointers, but they are not as scary as C pointers, as there is no pointer arithmetic. You just have the simple concept of a variable and its address in memory. 

Go liberates systems programming, such as server and network software from the clutches of C and C++ and brings it to the masses, making it easier to understand and actually enjoy writing server and systems software, not just yet-another web application. 

Go Pointers!!

Jun 20 2020
One of big myths in software industry was perpetuated by Joel Spolsky in his 2006 classic The Guerilla Guide to Interviewing. I love and respect Joel, and fully agree with the article, except the following paragraph. 

I’ve come to realize that understanding pointers in C is not a skill, it’s an aptitude.

In first year computer science classes, there are always about 200 kids at the beginning of the semester, all of whom wrote complex adventure games in BASIC for their PCs when they were 4 years old. They are having a good ol’ time learning C or Pascal in college, until one day the professor introduces pointers, and suddenly, they don’t get it. They just don’t understand anything any more. 90% of the class goes off and becomes Political Science majors, then they tell their friends that there weren’t enough good looking members of the appropriate sex in their CompSci classes, that’s why they switched.

For some reason most people seem to be born without the part of the brain that understands pointers. Pointers require a complex form of doubly-indirected thinking that some people just can’t do, and it’s pretty crucial to good programming. A lot of the “script jocks” who started programming by copying JavaScript snippets into their web pages and went on to learn Perl never learned about pointers, and they can never quite produce code of the quality you need.
For a long time, I believed this. Whenever I tried learning pointers in C, I'd struggle for a while, remember the above words and finally give up thinking pointers are not just not my cup of tea.

Then I started learning Go

One of the things that make Go syntax beautiful is how variables are declared. In most C-based languages, you write the type of the variable first, then the name of the variable. When reading a sentence, you have to read it from right to left. For example,
int x, y;     // x and y are integers
int *p;       // p is a pointer to an integer
However, in Go, the name comes first, followed by a type. So you read it from left to right. For example,
var x, y int;    // variables x and y are integers 
var p *int;      // variable p is a pointer to an integer
That brings me back to the subject of pointers and why I don't agree with the above paragraph, especially the line understanding pointers in C is not a skill, it’s an aptitude

When you are learning a new concept, especially a hard one like pointers, it matters a lot how it's being presented to you. When the concept doesn't make sense at first, it's easy to blame yourself and give up, rather than try to find a new teacher, tackling it from another angle, or learn it using a different approach. 

That's what happened with me when learning pointers in C. Often I'd start on solid grounds, understanding what is a pointer, and how it points to another object in memory, by containing the actual memory address of the location where that object resides. The trouble came when de-referencing that pointer to get the underlying value of that object. I'd always get confused between the meaning of * of de-reference and the * of declaration. 

In C, you'd do this:
int x, y;
int *p;
p = &x        // so far so good.
y = *p        // ???
In Go, you do it as shown below. Notice the second line, where we are defining p (not *p) as a pointer to an integer. This is not confusing (for me, at least) as it looks different from the pointer declaration. There's a clear distinction between a pointer and a de-reference from a pointer. 
var x, y int
var p *int
p = &x
y = *p       // de-reference p to get the value at the memory address it's pointing to
Agreed, you can do this in C:
int* p;
But this is not the same: 
int* p, q    // p is a pointer to an int, q is an int
In Go, this is how you declare two pointer to integers:
var p, q *int 
It was not until I started learning Go, that I finally understood how pointers work. That opened new doors into how computer memory works, why strings are immutable in C#, the difference between Value Types and Reference Types in C#, and much more, which would have been next to impossible without learning pointers.

So if you are a new developer, and struggling with pointers in C, I'd recommend learn them in Go first. Once you understand the basic idea, you can go back to C and the pointers start to make sense. But don't think, for a moment, that you are born without the part of the brain that understands pointers, just because Joel said so. 

Arrays in Go

Jun 14 2020
In Go, arrays are passed by values. When a function is called, a copy of the array is made and is assigned to the corresponding parameter variable in the function. Hence the called function receives a copy, and not the original.

In this example, all the values in grades array in main() are copied by value into grades array in change(). If I change one of the grade in change(), it won't be reflected in main()
func main() {
    grades := [3]int {1, 2, 3}
    change(&grades)
}

func change(grades [3]int) {
    grades[2] = 20 // caller doesn't see this change
}
Passing large arrays in this way can be inefficient, and any changes that the function makes to array elements affect only the copy, not the original. This behavior is different from languages that implicitly pass arrays by reference, such as C#.

In C#, the reference is passed by value. As arrays in .NET are stored on the heap, we have a reference. That reference is passed by value to the function, meaning that changes to the contents of the array will be seen by the caller. However, if we reassign that reference to another array, that change won't be visible. 
void Modify(int[] data) {
    data[0] = 1; // caller sees this
}
void Assign(int[] data) {
    data = new int[20]; // but not this
}
To pass an array by reference in Go, we have to pass a pointer to that array, so that any modifications the function makes to array elements will be visible to the caller. For example, the following function changes the contents of an array of 3 integers.
func change(ptr *[3]int) {
    ptr[2] = 20
}
You can call this by passing a pointer to the original array:
change(&arr)
Here is a complete example
package main

import (
    "fmt"
)

func main() {
    grades := [3]int {1, 2, 3}

    fmt.Printf("\nOriginal array:\n")
    for i, v := range grades {
        fmt.Printf("arr[%d] = %d\n", i, v)    // prints 1 2 3
    }

    change(&grades)
    fmt.Printf("\nModified grades:\n")
    for i, v := range grades {
        fmt.Printf("arr[%d] = %d\n", i, v)    // prints 1 2 20
    }
}

func change(ptr*[3]int) {
    ptr[2] = 20
}
Although passing a pointer to an array is efficient and allows the called function to change the caller’s variable, arrays are still fixed in size. Hence, slices are recommended, which are passed by reference and are dynamic in size. For example, 
func SliceDemo() {
    grades := []int{1, 2, 3}
    fmt.Println(grades)  // prints [1 2 3]
    changeSlice(grades)
    fmt.Println(grades)  // prints [1 2 20]
}

func changeSlice(grades []int) {
    grades[2] = 20
}
Here is the StackOverflow question that inspired this post, and my answer to it. 

Reclaiming Memory

May 15 2020
In programming, garbage collection refers to the process of programmatically cleaning up the memory allocated to objects that is not correctly in use.

For a long time, I thought that the variables defined in a block or a function are garbage collected when the program control reaches the end of the block, or when that function returns. I was surprised to learn that it's not the case, while having a fresh look at the pointers in Go.

A variable is garbage collected only when no path/reference to that variable exists from other members of the program, i.e. it can no longer affect the rest of the program.

Because the lifetime of a variable is determined only by whether or not it is reachable, a local variable may continue to exist even after its enclosing function has returned. A simple example demonstrates this.
var global *int
func f() {
    var x int
    x = 1
    global = &x
}
Here, x is not garbage collected when the function f() returns. The reason is, it's still reachable from the variable global, which is a pointer to an int, or x. As global has a reference on it, the garbage collector knows not to clean it, as it will break global, and it's allocated on a heap, not on stack. 
func g() {
    y := new(int)
    *y = 1
}
In contrast, when the function g() returns, the variable *y becomes unreachable and can be garbage collected, as no other variable is holding a reference to it. The compiler allocates *y on the stack. 

Why does that matter?

In a garbage collected language, such as C# or Go, you may wonder why knowing when a variable is garbage collected is important while programming, when you have so many other things to keep in your head at the same time.

Well, though I don't need to explicitly allocate and free memory, as the GC is taking care of that, but to write efficient programs, I still need to be aware of the lifetime of the variables.

For example, keeping unnecessary pointers to short-lived large objects, especially global variables, I am preventing the garbage collector from cleaning up these objects, which are taking up space, either in my RAM, or on L1 or L2 cache memory. It might not matter when we have gigs of free RAM nowadays, but it does matter when programming for embedded devices where each and every byte of memory is scarce.

Now that I think of it, garbage collection seems like a wrong choice of words for such valuable piece of data as RAM. I think reclaiming memory expresses the intent better, than collecting garbage. What do you think?

Naming in Go

May 14 2020
Go takes a radically different approach to defining the visibility of members.

There is no "public" or "private" label for items. The case of the initial letter of the identifier determines the visibility of that item.

If the initial character is an upper case letter, the identifier is exported (public); otherwise it is not. 

  • upper case initial letter: Name is visible to clients of package
  • otherwise: name (or _Name) is not visible to clients of package
This rule applies to variables, types, functions, methods, constants, fields. That's all there is to it. 

There's also no method overloading. For a given type, there's only one method with that name. 

This results in clarity and readable programs. The code itself expresses the programmer's intent. 

I love Go. 

Learning Go

May 13 2020
While learning about Docker, I kept hearing about the Go programming language, and why it's so awesome, fast, fun, and productive, again and again. So finally, as my bedtime read, I started browsing through Brian Kernighan's book, The Go Programming Language.

I have to say that I am thoroughly impressed with both the language and the book. In contrast to other programming books, it doesn't introduce you to the syntax and the basic concepts such as loops, conditions, etc. right from the first chapter. Instead, it takes you through a series of small to medium sized, but very real and powerful programs, to give a feel for the language. Instead of spending few days immersing into the basic syntax of the language and learning the beginner topics, the reader can decide if they do want to program in this language, and if they do want to keep reading. I think it's similar to showing a teaser for a movie.
gopher
For me, it was a great, tasty teaser for the language, which does fit my brain nicely. I was hooked after reading the first few pages of the book. The syntax seemed too enticing to lay in my bed and just keep reading the examples. 

So, I turned on my PC at 11 pm, downloaded a fresh install of Go, and started programming. In a couple of hours, I had written programs from a simple 'Hello, world' to a full-fledged web server, including a concurrent URL processor. 

Go has its unique idioms and style. If only you can liberate yourself from your current programming language and look at Go with a fresh set of eyes and a clear mind, you'll find it easier to understand and appreciate the Go's elegance. 

After the head-first dive into the deep end of the sparkling blue ocean that is Go programming language, I am now looking forward to the second chapter of the book, which gives a much formal introduction to the language.