PermalinkIntroduction
Many people are discussing this burgeoning language which is gaining traction with every passing day and steadily making its way into the market with promising opportunities.
Go, a statically typed, compiled programming language developed at Google by Robert Griesemer, has a syntax that is strikingly similar to C. However, it incorporates features like memory safety, garbage collection, and structural typing. Most notable among these is its unparalleled ability to manage concurrency.
One aspect that might initially intimidate people is its similarity to C, especially its use of pointers. It often provokes an exclamation along the lines of, "Wait, did you just say pointers? I thought I was done with those after graduation!".
Indeed, the use of pointers is a commendable aspect of Golang. This is primarily because, similar to the C language, it doesn't have reference data types as all values are passed by value. In programming, passing by value means making a copy in memory of the original parameter's value, effectively duplicating the contents of the actual parameter. Passing by reference, on the other hand, involves storing a copy of the address of the actual parameter.
While languages like Java have both reference datatypes and primitive types, Golang only has primitive types. There is a common misconception that Go types like maps, slices, and channels are reference datatypes, but that's not the case. What actually happens behind the scenes is that these are converted into pointers, which contributes to the confusion.
If you want to create a new type in Go, you'll need to create a struct. For example:
type Student struct {
ID string
Name string
LastName string
Course string
}
You might be wondering, why the attributes of that structure are uppercase, basically because lowercase attributes, functions and interfaces names are treated as private accessible within the package, which means that they can't be accessed outside the package they are defined, and the uppercase ones are exported.
As this article is just an introduction, we will talk a little bit about some Golang capabilities and how is the market behind this programming language.
PermalinkTypes on Golang
Go is a typed language, but it differs slightly from others. Unlike Java, which has primitive types and reference data types, Go has specified types for everything - to represent textual, numeric, boolean, pointer, composite, function, and interface values.
Variables in Go can be defined in the following way:
var counter = 5
var message = “Hello"
or
counter := 5
message := "Hello"
PermalinkZero Value
In Golang, there is the concept of a zero value, which is somewhat similar to undefined and null in JavaScript. However, unlike JavaScript, in Go, when a variable is not explicitly initialized, it assumes a "zero value," which is the default value for that type. For example:
var message string // default value ""
var factor float32 // default value 0
var enabled bool // false
PermalinkPre-Declared Types and Composite Types
In Go, the foundational types are the pre-declared or built-in types. These include string
, int
, uint
, byte
, rune
, float32
, float64
, and bool
. It’s important to note that while these types do hold their own value, the term "immutable" may not accurately describe their behaviour. These types' values can be altered, but changes do not affect other variables which may have held a copy of the original value.
As for composite types, they encompass arrays, slices, maps, and structs. These can either be named or unnamed. They are often referred to as unnamed when they are defined directly within the code using literals without an associated type declaration. Meanwhile, named composite types are defined with a name identifier paired with their structural definition.
Mutability in Go is associated with maps, slices, and channels. These types can have their elements directly modified. However, when they are passed to functions, what is actually passed is the internal pointer to the underlying data structure, not the complete data structure itself. This can give the impression of pass-by-reference-like behavior. Nonetheless, it’s crucial to highlight that Go is strictly a pass-by-value language. The "value" for maps, slices, and channels includes an underlying pointer to data. Consequently, while you can alter the elements within these structures, reassigning entirely new structures to a passed parameter will not affect the original structure in the caller.
PermalinkMemory Allocation
A useful method to demonstrate how memory allocation works is by comparing Golang with other languages. Let's first examine how memory allocation operates in Java.
In Java, memory is partitioned into the stack and the heap. The stack generally stores primitive types and references to objects, as well as call stacks for method calls. The heap, on the other hand, is where instances of classes (objects) are stored. When an object is created in Java, the object's attributes are stored in the heap, with a reference to that object stored in the stack. This setup paves the way for object mutability, as several references can point to a single object, and alterations done via any reference impact the original object.
Go also distinguishes between the stack and heap for static and dynamic memory storage respectively, but the semantics are somewhat different due to the language's design. In Go, each declared variable occupies a distinct memory location, regardless of how that variable is used or where it's stored (heap or stack). This means, unlike Java, it's not possible to have two non-pointer variables in Go refer to the exact same storage location.
However, Go does support pointers, which can be used to create multiple references to the same underlying data. But, these are not reference data types in the same sense as in Java. When you pass a variable to a function in Go, you're always passing the value of that variable. This applies to pointer variables as well -- what gets passed is the value of the pointer, i.e., the memory address it stores. So, while you can use pointers to share data between functions or goroutines, strictly speaking Go doesn't support pass-by-reference semantics as Java does.
PermalinkPointers
As discussed in the context of memory allocation, in Golang, two variables cannot share the same storage location. There is no concept of values being passed by reference. This implies that if you want to create a variable and change the value of the same storage location to which this initial variable points to within the scope of another function, you will need to create a pointer.
Here's how memory allocation works with pointers:
PermalinkReturn Any Number of Results
Another good thing is that this language is capable of returning multiple number of results on its functions, like:
func swap(x, y string) (string, string) {
return y, x
}
func main() {
a, b := swap("hello", "world")
fmt.Println(a, b)
}
PermalinkIf with a Short Statement
You can do a if with a short statement to execute before the condition, like:
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
}
return lim
}
there is also a way to execute a method, get its result, and validate if there weren't any errors:
func getUserEmail(userID string) string {
if userEmail, err := userService.GetUserEmail(userID); err != nil {
panic(err)
}
return userEmail
}
In this last piece of code, we can see that we are calling a function that returns two values: an email and an error. We can call the function and simultaneously evaluate the result in a concise if statement. If the error differs from nil (which is equivalent to null in some other languages), the program will encounter a panic error.
PermalinkGoroutines
Suppose we have a function call f(s). Here’s how we’d call that in the usual way, running it synchronously.
To invoke this function in a goroutine, use go f(s). This new goroutine will execute concurrently with the calling one.
package main
import (
"fmt"
"time"
)
func main() {
go func(msg string) {
fmt.Println(msg)
}("going")
time.Sleep(time.Second)
fmt.Println("done")
}
PermalinkChannels
Channels are one of the most exiting thing about Golang, channels are data structures that can receive values between threads, you can use this to establish communication between Goroutines.
For example, you can use channels to communicate the main Goroutine, that another Goroutine has finished its work, for example:
package main
import (
“fmt”
“time”
)
func say(s string, done chan string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
done <- “Finished”
}
func main() {
done := make(chan string)
go say(“Hello world”, done)
fmt.Println(<-done)
}
There are multiple ways you can use Channels, and also Golang has a lot of another packages that helps us in establishing synchronization between routines, also performing locking and others capabilities.
PermalinkMarket
With all this impressive capabilities, many companies started to use Golang, because it has a huge performance compared to other languages, and when we are talk about concurrency, Golang is the real champion, some examples that we could use Golang:
Cloud infrastructure: Golang can be used as the base language of infrastructure as code frameworks, and the most famous framework on that field, Terraform, is totally written in Go, using the power of concurrency management, to deploy in a effective way infrastructure in the cloud in many routines.
Media Platforms: Netflix, YouTube and another platforms use Go for video streaming services, and to fight against high loads on their applications.
On-demand servicers: The taxi giant Uber was looking to improve map processing speeds as people loaded geofence lookups, sending literally thousands of queries per second. Go helped Uber significantly reduce the timing of providing services to users, which was much appreciated by users.
Talking about salaries, the income of developers may vary depending the programming language they are working with, due to some points, for example:
Number of companies using it, and the capability of improving systems
Reliability within the community
Lack of labour force
For example, Golang it's not a popular language such as Python, but you may find Golang developers rate per hour way higher than Python.
The reason behind this is the trend of the language, combined with its reliability and the lack of developers, so by terms of demand and offer, we can get a clear picture why Golang pays more, which one is the easiest one to find, a Javascript developer of Go?
As money is one of the things that more puts people into action, this is a good reason to start learning Go, isn't it?