Go Basics
Table of Contents
Go - This article is part of a series.
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!"
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"
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
Go constants #
Constants are declared with the keyword const. Constants can’t use the := operator for declaration.
const Pi = 3.14
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
}
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
}
We can return multiple values from a single function
func swap(a, b int) (int, int){
return b, a
}
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
}
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);
}
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++
}
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++
}
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")
}
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")
}
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")
}
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.")
}
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.")
}
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")
}
The output will be,
hello
world
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")
}
Here the output will be,
counting
done
3
2
1
0
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!