Go for Ruby developers

Rubyists to gophers

If you are a Ruby developer and want to start with this cool new language Go, this can help you get started. In this blog, we will go through the basics and some cool features of GO along with its Ruby equivalent.

Ruby is a dynamic, interpreted, reflective, object-oriented, general-purpose programming language. It was designed and developed in the mid-1990s by Yukihiro “Matz” Matsumoto in Japan.
According to the creator, Ruby was influenced by Perl, Smalltalk, Eiffel, Ada, and Lisp. It supports multiple programming paradigms, including functional, object-oriented, and imperative. It also has a dynamic type system and automatic memory management.
Go (often referred to as Golang) is a programming language designed by Google engineers Robert Griesemer, Rob Pike, and Ken Thompson. Go is a statically typed, compiled language in the tradition of C, with the added benefits of memory safety, garbage collection, structural typing, and CSP-style concurrency. The compiler, tools, and source code are all free and open source.
— Wikipedia

Let’s start with our all-time example of printing “Hello World” for both go and ruby.

Ruby

Go

Try in Go Playground

Unlike Ruby where we can print “Hello World” with a single line, in Go, we need to write a few more lines of code. Let’s get deeper into the Go code.

In the Go program above, the keyword packagedefines the scope of the code i.e whether it is a library or an executable code. In the above example, with package main we are telling the Go compiler that the code is executable. Every executable program must always use package main.

The import is similar to require in Ruby, which pulls in external packages that will be used in the program. Here we are pulling the package “fmt” which is used for the input/output formatting.

The main() function is the entry point for the program execution. All the codes that need to be executed and run in Go, go inside this main function. In Go, opening curly bracket signifies there is code below it that needs to be executed and closing bracket signifies the end of the statement. So, the opening bracket must be on the same line of any block statement like functions, conditions.

How to run the code through the command line

Ruby

Copy the above ruby code to a file named hello_world.rb. “.rb” is the extension for Ruby source code. We can run a code in ruby using the command ruby <filename>

> ruby hello_world.rb
Hello World!!!

Go

Copy the above Go code to a file named hello-world.go. “.go” is the extension for Go source code. We can run a Go program in two ways which are shown below.

> go build hello-world.go
> ./hello-world
Hello World!!!

OR

> go run hello-world.go
Hello World!!!

Here, in the first one, we are first compiling the file and creating an executable binary file using the build command and then running the binary file. While in the second one, we are running the code using the go run command. This command creates the executable file behind the scene and then runs the code.

Commenting out code

In ruby “#” is used for commenting the code while in Go we use “//”. For multi-line code comment, it is “/* …. */”.

Ruby

Go

Variable

As Ruby is dynamically typed, there is no need to define variable types. While Go being a statically typed language, we need to define the type during the declaration.

Ruby

Go

As we can see in the above example, though Go is a statically typed language, it gives the feel of dynamic type by evaluating the value assigned and declaring the type to the variable on the fly.

Data Types

Some of the variable data types declarations for Go are listed below.

In Ruby, we can assign a different data type value to an already defined variable of different type but is not possible in Go.

Hash/Map

As in Ruby, we can also define a hash object in Go. In Go, hash is called map. The type syntax for the map is map[string] int, where the datatype inside bracket specifies the key data type and the other one, at last, specifies the type of value.

Go equivalent of Ruby Hash

Check if a key is present in the map

We can check if a key is present in the map with a two-value assignment. In the example below, if the name has key “last_name”, then “ok” is true and the lastname variable holds the lastname value else “ok” is false.

Array

Like in Ruby, we have an array in Go as well. However, in Go, we will need to define the length of the array during the declaration.

Slice

Arrays are limiting for cases when the values of array changes in runtime. Arrays also do not provide the ability to get subarray. For this, Go has a data type called slices. Slices store sequence of elements and can be expanded at any time. Slice declaration is as similar as array declaration without the capacity defined:

Now, let’s look into some of the cool uses of slice and compare it with Ruby.

Append elements to Array

In Ruby, we use + operator to append elements of an array to another array. While in Go, we use append function to append elements to an array/slice.

Sub Slicing Array

Copy Slice/Array

In Ruby, we can simply copy an array to another one by assigning one array variable to another. While in Go, we cannot copy slices directly using assignment. We will need to first initialize a destination array with the required length and then use the copy method.

Note: The number of items copied to the destination is determined by the length of the destination array:

Here only first 2 elements are copied because the length specified for variable b is only 2.

Condition

If…else

If a scope of a variable is within the if block only, then we can assign and check condition in the if condition itself as shown below:

if name, ok := address["city"]; ok {
// do something
}

Switch Case

The execution of the switch case in Go is similar to Ruby i.e it only runs the selected case, not all the cases that follow. We use switch..case syntax in Go unlike case..when syntax in ruby.

Type switches

It is like a regular switch statement with the type specified for the switch case. We can learn more about it here: https://tour.golang.org/methods/16

Loop

In Go, we only have for loop. However, we can use for loop to achieve different other kinds of loops as supported by Ruby which can be seen below:

Normal For Loop

While Loop

There is no while keyword in Go. Instead for loop can be defined in a way to achieve the while loop as shown below.

Infinite loop

Each Loop

In Go, we have for loop with range which is similar to each in Ruby.

Each With Index

Error Handling

In ruby, we do the error handling using begin rescue block.

In Go, there is a concept of Panic, Defer and Recover for raising error and rescue. However, It is extremely rare that we will need to handle panics in our code as these are generally handled by the framework and library code.

We can see in the example below, how an error is raised using Panic, and then recovered from this through the recover keyword which is inside the defer block. A defer statement defers the execution of a function until the surrounding function returns. So, in the example below, when there is panic the execution halts. Although the flow halts, but the defer statement gets executed. Thus, the recover statement inside the defer then gets executed which acts as a rescue block in Ruby.

As mentioned earlier, we generally do not use Panic in the application code. Instead, we have an error interface that we use to check any error and take the action accordingly as shown in the example below.

Defer

It is similar to Ensure statement that we use in ruby.

Defer is used to ensure that a function call is performed later in a program’s execution, usually for purposes of cleanup. Some of the use cases of the defer are to close the opened file, close the HTTP connections etc.

Functions

In Ruby, we do not need to specify the return type as well as the argument type. While in go it is necessary to define the return type and also the argument type. Note that a return statement is required in Go else nothing will be returned whereas in ruby the return statement is not necessary. Ruby automatically returns the last line inside the function.

Pointer

In Ruby, we don’t have the concept of pointers. In Go, we have pointers which hold the memory address of the value. It is represented by the “*” operator. We have another operator &, which gives the memory address of the value. It generates a pointer to its operand. The example below shows the referencing and dereferencing of a pointer.

Object-Oriented programming

Go isn’t an object-oriented language. Instead, they have the concept of a struct. We have functions attached to this struct. We can then access the variables and functions attached to the struct by creating an instance of the struct.

Go Playground

In the above example, we have defined a new type Festival with the help of struct. As we can see in the example we have created two functions “IsDashain” and “ToString” which is of type Festival. These functions are accessible through the instance of the Festival struct. In Go, these kinds of functions are called methods. Whereas in Ruby method and function are synonymous. Also, if we see the method definition, we are creating a method of festival pointer type. There are two important use-cases of making pointer receiver.

  1. When we need to modify the receiver, the receiver must be the pointer. In the above example, when the festival is “Dashain”, the pointer method changes the value of the festival which is now accessible to the main method.
  2. If the request argument is large, having pointer receiver would be cheap and efficient as we will only be passing the address and not the large argument.

Note: Go provides support for an interface which gives the feel of ruby inheritance/mixing and much more flexibility of OOP concepts.

Public/Private methods and variables

In Ruby, we define private methods by using keyword private. Anything written below private keyword is private. While in go defining private functions and variables can be achieved by defining methods/variables with a lowercase letter at the beginning of the method name.

JSON encoding/decoding:

We use Marshal method of json for JSON encoding and Unmarshal method for JSON decoding in Go.

JSON Encoding

Go Playground

JSON Decoding

Go Playground

Note: In the above example `json:”page”` command maps the page key of the input json to the Page attribute of the struct.

Package:

Packages in Go are similar to gems in Ruby. In Ruby, we install the gem with “gem install <gem name>”. While in GO, we install packages with “go get <package path>”.

We also have different Go standard packages defined. Some of the commonly used packages are:

fmt

As per the naming, the package is used for formatting. This is a very handy package. In Ruby, we follow rubocop guidelines for the formatting. However, in Go, we need not worry about it. The fmt package takes care of it. After we work on the code, we can simply run:

gofmt -w yourcode.go
//OR
go fmt path/to/your/package

The code will be formatted automatically.

log

This package is similar to logger of Ruby. It defines a type Logger with methods for formatting output.

net/http

This is used for making HTTP requests. This is similar to net http in ruby.

Concurrency in Go:

Unlike in Ruby where we need to use different libraries such as celluloid for concurrency operations, Go language has built-in concurrency provided. We can simply run concurrent operations in go by using “go” keyword in front of the operation. As shown in the example below, we are executing a function with parameter “goroutine” concurrently with the main function by simply writing “go” keyword in front of the function call.

There is another concept called Channels which is used for the communication between the two goroutines. With channel, we can send and receive values between the goroutines.

Explore more on Go:

  1. https://golang.org/doc/effective_go.html
  2. https://play.golang.org/
  3. https://tour.golang.org
  4. https://gobyexample.com/
  5. https://www.safaribooksonline.com/videos/mastering-go-programming/9781786468239