A young woman typing on her laptop in a cafe

Going the Golang Way

Professional headshot of Shalami Patil
By Shalmali Patil, Team Lead, Engineering
June 6, 2019

For about six years, I developed web applications and micro-services using Java. I had fun watching Java make life easier for developers over time,. Eventually, I got an opportunity to join a team at PubMatic that was building a high-performance, low-latency server-to-server application. The team had chosen the Golang programming language, also known as Go, given its good track record for similar use cases. This was the beginning of an exciting journey of learning Go, and the more I learn, the more amazed I am by all the fun and powerful things this language has to offer.

How Java And Go Differ

Java and Go are similar in many ways – both are strongly typed and have garbage collection, packages, interfaces, and support for concurrency. However, Go does a few things differently that surprised the Java-developer in me. Here is an overview of a few key differences and highlights:

  1. If you declare it, you must use it!

Go doesn’t allow unused local variables and will throw a compile time error if it catches any.

There is, however, a special placeholder in Go called the blank identifier (“_”) which is useful when you want to discard values returned by a function, thereby not wasting an actual variable to store the value. It can also be used for loops and maps.

for _, value := range myArray {

sum += value

}

  1. Go doesn’t have access modifiers

Go doesn’t have explicit access modifiers like Java’s “public” and “private.” However, it employs a simple mechanism for managing the accessibility of variables and functions. For instance, if the variable or function name begins with a capital letter, it is accessible outside the package. Thus, a public function declaration in Java could look something like this:

public Account getAccountDetails();

In Go, it would simply be:

Account GetAccountDetails()

  1. Compact, implicit variable declarations with Go

Go provides a “:=” construct for variable declaration and assignments with implicit type. So, the following statement would create a string variable assigning the value “PubMatic” to it without the need to define it as a string:

name := “PubMatic”

  1. Returning multiple values from a function

Functions can return, at most, one value in Java. Go, on the other hand, supports multiple value returns. This is especially useful for returning both the result and potential error from a function. An example for a function returning two integers is:

func getValues() (int, int) {

return 10, 20  // returns two integers!

}

  1. Do it later, alligator!

Defer in Go allows you to define a set of statements that would run just before the current function returns. You could perform any clean up actions (like closing a file) using this functionality. There are similarities to Java here:

func readFileContents(filename string) {

f, err := os.Open(filename)

    if err != nil {

panic(err)

}

defer f.Close()

// code to read the file

}

What Makes Go Special

Here are a few of Go’s features that developers appreciate:

  1. Speed

Go is a compiled language, which makes it perform faster than interpreted languages. It also has excellent compile time. Building our Go application, a process which ended up generating an executable 21MB, now takes only seconds!

  1. Garbage collection

Go has automatic garbage collection, which keeps code clean and safe. The Go compiler efficiently decides whether a variable should be stored on the heap or on the stack.

  1. Concurrency

The concurrency model in Go is simple to use, compared to other languages.

  1. Goroutines

Goroutines allows you to achieve concurrency.  It is a thread of execution that works in parallel with other Goroutines.

Here is an example in which we invoke two Goroutines that would execute asynchronously:

func main() {

// Functions f1 and f2 are invoked in goroutines.

go f1()

go f2()

}

  1. Channels

Channels are how multiple Goroutines communicate with each other, A Goroutine can send values into a channel and another goroutine can receive those values from the same channel:

func main() {

data := make(chan string)    // create a channel

go f1() {

data <- “hello”   // this goroutine pushes the string “hello” onto the channel

} ()

receivedData := <- data  // Receive data from the channel

fmt.Println(receivedData)

}

  1. Easy to Learn

Go has a good standard library and built-in support for testing, benchmarking and performance measurement, which makes it a great choice for developers.

Should You Go For Go?

What I love about Go is its simplicity and ease of use. Our application requires concurrency support while handling high loads, without compromising on response time. Go has proven to be a great choice. For our customers, this means faster page loads and stable functioning under heavy loads, thereby driving more revenue.

While Go was initially used mainly for systems programming, there has been a trend in using Go for network programming, DevOps, and web development. It has worked well for us and the team is benefiting from the new language. To learn more about our work in engineering, check out our recent technical content or review open positions to join our team.