A Review of the Go Language

Go is a modern, procedural, concurrency oriented language. It is started by Rob Pike and Ken Thompson et al. The language is defined to be a “general-purpose systems programming language”. I have played with Go for a short while, and have some opinions about it. I’ll discuss these ideas in this blog post.

Go has good sides to it more than bad. Using a small syntax, it remembers of C at the first glance. Go is a procedural language, just like C is. But in contrast to C, one has ability to use function literals, which can be useful at times. Go is a concurrency-oriented language, which is a popular marketing buzzword for newborn languages nowadays. In contrast to most concurrent languages, Go is an imperative language. Offering the so-called goroutines, Go language brings a different way of writing concurrent programs.

Go creators are quite eager about reducing the compilation time. Rob Pike has criticized the dependency model of C/C++ in some keynotes. The language is very strict about dependency management. Imports are module based, in contrast to the C model of header files and file inclusion. This is, quite frankly, very nice. The module is the code and the code is the module. Management of name visibility has been undertaken nicely (ignoring the issue of imposed naming convention). There is no questions possible about visibility of a name throughout the package.

Go language design tries to reduce typing whenever possible. Type inference is used nicely to prevent C++ style unnecessary syntax like Foo<Bar> foo = new Foo<Bar>(baz);. Interfaces feels somewhat absurd in the beginning, but very convenient in time. One does not need to explicitly declare that he implements an interface; if the methods declared in interface is defined for the data structure, it implements the interface.

Allocation of memory is handled nicely, although deviating from what a systems language remembers me of: Go is a garbage collected language which exposes no primitives of explicitly managing memory manually. This means it is inconvenient if not impossible to implement operating systems or drivers in Go. Being mainly targeted towards networked and concurrent systems, this is the right decision too.

Go offers very convenient syntactic sugar for arrays, array slicing and hashmaps. Also, the syntactic constructs for deferring jobs to the end of functions and creating small so called goroutines are nice. But, Go code looks hairy at the top of function declarations and control flow statements. Go has a for loop only, and you have to use it for any kind of iteration you want to do. It can become a traditional while loop or a Python style for-in-range loop, which is a bit cumbersome. If statements have initializers like for loops, which is cumbersome most of the time, even with short statements.

Goroutines and channels are main concepts of concurrency in Go. One can easily fire off a function inside a goroutine and use a channel to pass back data. Although the concept is cool, I did not really like it and feel natural with it.

Go is very, very, very, very, very strict about being thrifty. The compiler is quite parsimonious about giving you imports and variables, and yells every single fucking time an unused variable/import is encountered. Don’t comment out an expression to just see if it works, it possibly won’t compile even if the function is valid. fmt is the package containing the Print* stuff, and if you use them to debug, be careful about commenting them out! You will have to go to the top of your file more often than you’d ever before. And this is not even a warning, it is a compile error! A very silly, inconvenient and, and basically an annoying feature. If the compiler knows that it is not used, it may just throw it away, discard it and not give it a fuck. The syntax/import tree can be shaked. And this will not create a performance penalty too; you anyway check it to see if it is used. It is not an error to declare a variable and not use it (or put it there to come back later). It is not an error to temporarily comment out some flipping printf. This bit me a lot :)

Go syntax, too, is very strict. The compiler imposes a very strict syntax. A very unreadable syntax, mainly for the control flow and function headers. You don’t have a chance to put braces to the newline, because Go people apparently wanted to keep all the parens for the function headers. You need braces even for a one-liner if/for statement. A one-liner void function with a single if statement involves at least 4 braces. But you are lucky to save a couple of parens from your if. If your function has a receiver and returns a tuple, it involves at least 3 couples of parens. if has an initializer, which is totally illogical. Go guys tries to impose a clear and succinct syntax with the expense of a clear and succinct syntax.

Go also does not have generics, but I did not use Go so much to see if this is a problem or a gain. I don’t believe authors of languages like Haskell, Scala, C++, Java et al. are wrong about the importance of this concept. And, Go neither offers any kind of overloading, so, the only way to not duplicate code is to use interfaces.

There is two major compilers for Go: 6g et al series of compiles, directly from the core team and gccgo which is a GCC frontend. Both are in C. Go is not a self contained language, which, in case of a natively-compiled statically and strongly typed language is a lack in my opinion.

In conclusion, I did not like Go. It’s syntax is stricter than Python with no apparent reason and even adulterates their points of clear code sometimes.

Thanks for dallying away here! I wish you enjoyed your read. And, I definitely suggest you to take a tour of Go to see how you like it. Even if you don’t like it, a new language is a new romance for the hacker. Have a nice day!

Intro to NPM Packaging.

I just forged my first experimental node package, and decided to put up a little tutorial here. I’ll assume you have the environment set-up; otherwise follow this link to do so. You also will need git, but you may do without it too.

NPM.

NPM is the de-facto package manager for node.js. I’s written by Isaac Schlueter. It may be used to install, create and publish Node packages. It is written in JavaScript and it is bundled with recent Node releases. A Node package is made up of node modules. Node implements the CommonJS module system, and frankly, it is weird and ugly, but it works.

Node Module System.

A node file, by itself, is actually a module. All declarations inside a file is private by default, that is, it is only available in the file it exists; a bit like static variables and functions in C. To publicize a variable, to export, it should be inside the exports object:

    /* ~/hello.js */
    var x = 12;    // This is visible inside this file.
    exports.y = x; // This is public.

    /* ~/mo.js */
    var hello = require('./hello.js');
    console.log(hello.x);  // ERROR ERROR ERROR
    console.log(hello.y);  // => 12
    

Package.

A node package is a collection of node modules (those are, javascript files), and a package.json file. JSON is a data exchange format. It is a subset of JavaScript syntax, namely, the object syntax. If you know Python, it looks like the dict literal. One need not has to know a lot about JSON to create and manage node packages.

package.json provides metadata for package, and as the most important info, it provides the entry point for the package. This entry point is a path to a javascript file. This file is loaded when you write require('a_package');.

Let’s Start.

As I’ve covered the basics, we can start the actual thing now.

First, get the git repository that contains some code we can use. Then, change branch to before-npm:

    $ git clone https://github.com/gkya/node_web.git
    $ git co before-npm

You’ll see a README file and a lib folder. This directory is not currently a node package. We’ll just make it one in a moment.

npmjs.org

npmjs.org is a repository/registry of node modules. When you npm install a package, it is fetched from this website. If you want to publish your packages, you will need an account. It’s quite easy to get one. Just run npm adduser <username> and fill out the prompts to obtain one.

Initialize a Package.

Inside the directory where code files are, run npm init. Fill-out the prompts. When you are prompted for the Main module/entry point: (none), type ./lib/web.js, if you are using the git repo I’ve provided. Otherwise, type in the path to your script. After this process, a package.json will get created. If you check out the master branch in the git repository I’ve provided, you will see my package.json file.

Publish a Package.

To publish a package, run npm publish. This will publish your package to npmjs.org/packages/<your-pkg-name>. You may omit this. A package that is not published is still a package.

Test.

In a distinct directory than our package, create a directory and cd into it. Then create a directory with the name node_modules. Then, copy the package into this directory. If you used my example code, you can use it like this:

    ~$ mkdir test; cd test; mkdir node_modules
    ~/test$ cp -rv ~/node_web node_modules
    ~/test$ cat << EOF > hello.js
    > var server = require('node_web').run();
    > EOF
    

Now you can run the hello.js with node hello.js, and if JS gods are not angry, it will run.

Conclusion.

We’ve forged a toy node package, and chances are published it to npm. I hope this article has been helpful to you. Have fun!