Go Basics

Vignesh Muthukumaran - Jun 19 '22 - - Dev Community

As I continue to explore Go for some side projects, I am familiarizing myself with some of the basic constructs of Go. Most of this article will be going through the syntax and some unique concepts of Go.

Variable declaration

One of the most basic things that we do in any language is to define variables. Below is an example of variable declaration and initialization in 2 ways. Before getting into that, just know that Go is a statically typed language, which means that the type of the variables is determined at the time of compilation itself.

Declaration and Initialization

Let's understand with an example the different types,

var message string = "Hi There!"
Enter fullscreen mode Exit fullscreen mode
Token Explanation
var Keyword to tell that we are declaring a variable
message Name of the variable
string Type of the variable
= Assignment Operator
"Hi There!" Value assigned

Instead of us explicitly writing down all the keywords and going the traditional way to define a variable in a statically typed language, in Go we can rely on the compiler to do some inference for us. Below is an example of Short Variable Declaration.

message := "Hi There"
Enter fullscreen mode Exit fullscreen mode

Here, the Go compiler infers based on the value that the type of message is a string.

Also, note that := can be used only for declaration. But we need to use = for reassigning values.

Variables can be initialized outside the function but not assigned a value. So, := is not usable outside a function.

We can assign multiple values in a single line as well as different types too.

var i, j int = 1, 2
a, b := "string", false
Enter fullscreen mode Exit fullscreen mode

Go constants

Constants are declared with the keyword const. Constants can't use the := operator for declaration.

const Pi = 3.14
Enter fullscreen mode Exit fullscreen mode

Go functions

One of the key differences in Go from other languages such as Java is that the type of variables or return type of functions comes after the variable name or function name. Below is a simple example of a function

func formMessage(message string) string {
    return "Hi There!, The message is " + message
}
Enter fullscreen mode Exit fullscreen mode

Some cool syntax in Go is illustrated below,

Shortening the function definition, if the types of arguments are the same. Here, instead of (a int, b int), we went with (a, b int)

func sum(a, b int) int{
    return a + b
}
Enter fullscreen mode Exit fullscreen mode

We can return multiple values from a single function

func swap(a, b int) (int, int){
    return b, a
}
Enter fullscreen mode Exit fullscreen mode

We can have something called a Naked Return, where we can have Named Return Values.

func swap(a, b int) (x, y int) {
    x = b
    y = a
    return
}
Enter fullscreen mode Exit fullscreen mode

We can name the return values, this internally makes it so that the variables are declared at the first line of the function. So a return with no values(Naked Return), we take and return these values. Be careful when using them as it can make the code less readable.

For Loop

For is the only loop construct in Go. The basic syntax has the 3 components present in any language.
| Operation | Execution Time | Remarks |
|----------------|------------------------|-----------------------------------|
| Initialization | Before the first iteration | Can be a short declaration |
| Condition | Before every iteration | Loop stops on evaluating to false |
| Post Statement | End of every iteration | Usually increment or decrement |

/*Print first 10 numbers*/
for i:=1; i <= 10; i++ {
    fmt.Println(i);
}
Enter fullscreen mode Exit fullscreen mode

One of the key differences between Go and other languages in the syntax as you can see is that it doesn't surround the 3 components of for loop with parenthesis. Also, the pair of braces {}, is always required, even if its a single line

The initialization and post statement is optional, we can have a for loop with only a condition.

/*Print first 10 numbers*/
i := 1
for ; i <= 10; {
    fmt.Println(i)
    i++
}
Enter fullscreen mode Exit fullscreen mode

In Go, for is while. Just use for like how you would use while in any other language.

/*Print first 10 numbers*/
i := 1
for i <= 10 {
    fmt.Println(i)
    i++
}
Enter fullscreen mode Exit fullscreen mode

If Statements

if also follows the same syntax for, the expression need not be surrounded by parentheses ( ) but the braces { } are required

if i % 2 == 0 {
    fmt.Println(i, "is even")
}
Enter fullscreen mode Exit fullscreen mode

We can have variables declared in if to be used inside the if block scope.

no := 10
if i := no % 2; i == 0 {
    fmt.Println(no, "is even")
}
Enter fullscreen mode Exit fullscreen mode

Else block is the same as any other language.

no := 10
if i := no % 2; i == 0 {
    fmt.Println(no, "is even")
}
else {
    fmt.Println(no, "is odd")
}
Enter fullscreen mode Exit fullscreen mode

Switch Statements

The switch is similar to other languages, but it only evaluates the condition that matches. So effectively there is no break needed. Also, Go cases can be anything, not just constants that are integers. Case statements stop the moment a case is executed.

fmt.Println("When's Saturday?")
today := time.Now().Weekday()
switch time.Saturday {
case today + 0:
    fmt.Println("Today.")
case today + 1:
    fmt.Println("Tomorrow.")
case today + 2:
    fmt.Println("In two days.")
default:
    fmt.Println("Too far away.")
}
Enter fullscreen mode Exit fullscreen mode

A switch can also be used as a clean way to avoid a long if-else ladder.

t := time.Now()
switch {
case t.Hour() < 12:
    fmt.Println("Good morning!")
case t.Hour() < 17:
    fmt.Println("Good afternoon.")
default:
    fmt.Println("Good evening.")
}
Enter fullscreen mode Exit fullscreen mode

Defer

Defer is something that is not available in all other languages. Essentially it defers a function execution until the surrounding function returns. The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.

func main() {
    defer fmt.Println("world")
    fmt.Println("hello")
}
Enter fullscreen mode Exit fullscreen mode

The output will be,

hello
world
Enter fullscreen mode Exit fullscreen mode

The Println function call is deferred till the return of the main method.

Defer uses a stack. The calls are pushed into a stack, so the order of return is LIFO(Last In First Out).

func main(){
    fmt.Println("counting")
    for i := 0; i <= 3; i++ {
        defer fmt.Println(i)
    }
    fmt.Println("done")
}
Enter fullscreen mode Exit fullscreen mode

Here the output will be,

counting
done
3
2
1
0
Enter fullscreen mode Exit fullscreen mode

As you can see, it returns in the reverse order of execution.

I hope, this article would have helped you grasp some of the basic constructs of Go. In the next article, we will build upon this and start exploring structs, slices, and maps. Soon, we will start with co-routines and threading. Happy Coding!


Leave a ❤️ comment and let me know what you think.
Do you enjoy what you’ve read so far? Consider checking out my site at https://vigneshm.me.

. . . . . . . . . . . . . . . . . . .