Geek Tech
GeekTech

GeekTech

Everything you need to know about Go-Lang - #2

Everything you need to know about Go-Lang - #2

Geek Tech's photo
Geek Tech
·Feb 13, 2022·

15 min read

Subscribe to my newsletter and never miss my upcoming articles

Table of contents

You probably have heard about Google's cool language called Golang. Golang is a statically typed, compiled programming language designed at Google by Robert Griesemer, Rob Pike, and Ken Thompson. It is similar to C/C++, but with memory safety, garbage collection, structural typing, and CSP-style concurrency.

This is the continuation of Everything you need to know about Go-Lang - #1, so if you have not read that then check that out first.

In the last part we have learned about Printing and Variables. We'll start off from where we left.

Constants

We have learned about variables. They are like a container which stores values of a type and can be reassigned with other values of the same type. In short that means we can change the values of variables. Now this might seen a good thing, but often time we use variables whose value we don't change at all. It's a good practice to define those as constants instead of variables. To define a value as constant we use the const keyword.

Example:

const pi = 3.14
const e = 2.71828
const sum = pi + e

const keyword works pretty much the same as var except you cannot change it's value. Using Constants when needed is a good practice and is beneficial to compiler sometimes. We can also declare the type of constant the same way as we do to variables.

const aWord = "This is a constant whose content cannot be changed"

If you are coming from other languages you maybe thinking that go follows a convention of writing constant in UPPERCASE. However, in go constant name is generally written in camelCase instead of UPPERCASE. The main reason is that variable or constant names which start with capital letter are those to be exported, if your variable or constant will not be exported to then it's useless to start it with UPPERCASE.

Your Turn

Try using constants in your previous programs of Golang instead of var for those whose values that aren't changing.

Operators

In Go, there are various kinds of operator that used for certain functions. These operators can be differentiated into:

  1. Arithmetic Operator.
  2. Relational Operator.
  3. Logical Operator.
  4. Bitwise Operator.
  5. Assignment Operator.
  6. Misc. Operator.

Arithmetic Operator

We have used Arithmetic Operator earlier. Let's learn about them again. Arithmetic Operators are used to perform, mathematical operations like addition, subtraction, division, multiplication, and modulus (remainder).

  1. Addition: The + operator is to add two operand.
  2. Subtraction: The - operator is to subtract two operand.
  3. Multiplication: The * operator is to multiply two operand.
  4. Division: The \ operator is to divide two operand. Dividing two integer returns an integer.
  5. Modulus: The % operator return the remainders of two operand.
package main
import "fmt"

func main() {
    a := 20
    b := 2
    fmt.Println("Sum = ", a + b)
    fmt.Println("Difference = ", a - b)
    fmt.Println("Product = ", a * b)
    fmt.Println("Quotient = ", a / b)
    fmt.Println("Remainder = ", a % b)
}

Output:

Sum = 22
Difference = 18
Product = 40
Quotient = 10
Remainder = 0

Relational Operators

Relational operators are used for comparison of two expressions. Relational operators return true if the condition satisfies or else it returns false. Here are the Relational operators:

  1. ==: Is equality operator, it is used to check whether the left and right-hand side operands are equal. It returns true if both are equal or else returns false.
    fmt.Println(3 == 3)
    fmt.Println(4 == 5)
    fmt.Println(2 == 2.0)
    
    Output:
    true
    false
    true
    
  2. !=: Is the not equal to. It is used to check whether the two operands are different. It returns true if they are not equal and returns false if they were. ! is the not operator.
    fmt.Println(3 != 4)
    fmt.Println(5 != 10 / 2)
    fmt.Println(3.14 != 22 / 7)
    
    Output:
    true
    false
    true
    
  3. >: Known as greater than operator. It is used to check whether the left-hand is greater than the right-hand side. It returns true if the left-hand side operand is greater than the right otherwise it returns false.
    fmt.Println(4 > 5)
    fmt.Println(5 > 5)
    fmt.Println(6 > 5)
    
    Output:
    false
    false
    true
    
  4. >=: Known as greater than equal to operator. It is used to check whether the left-hand side operand is greater than or equal to the right-hand side. It returns true if the left operand is greater than or equal to the right-hand side or else returns false.
    fmt.Println(4 >= 5)
    fmt.Println(5 >= 5)
    fmt.Println(6 >= 5)
    
    Output:
    false
    true
    true
    
  5. <: Known as lesser than operator. It returns true if left-hand side is lesser than the right-hand side, or else returns false.

    fmt.Println(4 < 5)
    fmt.Println(5 < 5)
    fmt.Println(6 < 5)
    

    Output:

    true
    false
    false
    
  6. <=: Known as the lesser than equal to operator. It returns true if the left-hand side is lesser than or equal to the right-hand side, or else returns false.

    fmt.Println(4 <= 5)
    fmt.Println(5 <= 5)
    fmt.Println(6 <= 5)
    

    Output:

    true
    true
    false
    

    Logical Operator

    They are used to combine two or more conditions or to change the checking of the original statement. The logical operators are:

  7. &&: The logical and operator returns true if all the conditions that are being joined by it are true.
    fmt.Println(true && false)
    fmt.Println(6 > 5 && 10 > 9)
    
    Output :
    false
    true
    
  8. ||: The logical or operator returns true if any of the conditions that it joins are true.
    fmt.Println(true || false)
    fmt.Println(6 > 5 || 10 > 9)
    
    Output:
    true
    true
    
  9. !: The logical not, also mentioned as not operator earlier, negates the result of the expression.

    a := 5
    fmt.Println(!a == 5)
    fmt.Println(!6 == 5)
    

    Output :

    false
    true
    

    Bitwise Operators

    In Go language, there are 6 bitwise operators which work at bit level or used to perform bit by bit operations. Bitwise operators works with binary. Following are the bitwise operators:

  10. & (bitwise AND): Takes two numbers as operands and does AND on every bit. The result of AND is 1 only if both bits are 1.

  11. | (bitwise OR): Takes two numbers as operands and does OR on every bit of two numbers. The result of OR is 1 any of the two bits is 1.
  12. ^(bitwise XOR): Takes two numbers as operands and does XOR on every bit of two numbers. The result of XOR is 1 if the two bits are different.
  13. << (left shift): Takes two numbers, left shifts the bits of the first operand, the second operand specifies the number of places to shift.
  14. >> (right shift): Takes two numbers, right shifts the bits of the first operand, the second operand specifies the number of places to shift.
  15. &^ (AND NOT): This is the bit clear operator.

Assignment Operators

Assignment operator is used to assign values to a variable. The left-hand side is the variable and the right-hand side is the value. Different types of Assignment Operators are:

  1. =: Known as equals to. It assigns the values at the right to the left-hand side.
  2. a +=: Other form of writing a = a + ..., where a is a variable.
  3. a -=: Other form of writing a = a - ..., where a is a variable.
  4. a *=: Other form of writing a = a * ..., where a is a variable.
  5. a /=: Other form of writing a = a / ..., where a is a variable.
  6. a %=: Other form of writing a = a % ..., where a is a variable.
  7. a &=: Other form of writing a = a & ..., where a is a variable.
  8. a ^=: Other form of writing a = a ^ ..., where a is a variable.
  9. a |=: Other form of writing a = a | ..., where a is a variable.

Conditional Statements

Suppose you ask your friend to buy you a lego space shuttle for yourself, but if it isn't available then buy a lego star wars. Over here you can see that we have a condition for us that if a lego space space shuttle then buy it or else buy a lego star wars. In the world of computers, programmer often face the same situation, where they need to so check if a certain condition is true then execute one set of commands, or else execute another set of commands.

In Go there are two types of Conditional statements

  1. If / Else
  2. Switch-Case

If / Else

if keyword is used to check whether one condition is true. If the condition is true then it executes the code block. Or else it doesn't execute that block. The syntax of if is every simple :

if condition { // <= `true` 
    statements
}

Here's a simple example:

t := true
if t { //<= true
    fmt.Println("The statement here is true")
}

Before I give any further examples, we need to talk about operators.

The equality operator == is use to check where that the left-hand side and right-hand side of the operation are equal. This is not to be confused with the = equal to , which is used to assign values from right to the left.

Let's now see some more examples:

if 10 / 2 == 5 { //<= true
    fmt.Println("Condition ", 10 / 2 == 5)
}

Output:

Condition true

10 / 2 == 5 returns true. Let's now see another example where our condition isn't true and see the output.

if 10 / 2 == 3 { // <= false
    fmt.Println("Condition",10/2==3)
}

Output


As we see we receive no output as our condition didn't satisfy and hence didn't enter the block.

In the last example we saw how if our condition doesn't satisfied then it doesn't print anything. If we want do execute some other statements when the condition doesn't satisfy we can use else keyword, right next to the closing braces of the if. Here's an example:

if 10 % 2 == 0 {
    fmt.Println("Condition true")
} else {
    fmt.Println("Condition true")
}

Output :

Condition true

We can also use else if statement if we want to add another condition. Example :

var a , b int
fmt.Scanf("%v %v", &a, &b) // takes user input and splits it by space
if a > 5 {
    fmt.Println("More than 5")
} else if a == 5 {
    fmt.Println("Equal to 5")
} else {
    fmt.Println("Less than 5")
}

You might want to check about different operators, as it will be helpful in the future.

Switch case:

When you have too many conditions to check from, using if else if else might be time consuming, so a better and more efficient way would be using switch case. Here's the syntax of switch case :

switch value {
    case value 1:
    case value 2:
    default:
}

Switch can compare values and executes the piece of code of that case. This is especially helpful during menus where user input depends on what to do.

var v int
fmt.Scan(&v) // takes user-input
switch v {
    case 1: fmt.Println("1")
    case 2: fmt.Println("2")
    case 3: fmt.Println("3")
    case 4: fmt.Println("4")
    default: fmt.Prinln("Other value")
}

This block of code compares the value of v with the values written after case and before :. Now if you are coming from other languages then you must be thinking the above code is technically wrong as if any of the cases gets executed those below it will get executed too, known as fall-through error. Fall-through error is an error that causes the fall of control of the program. It is common in other languages like C/C++, Java, etc. However in Go, fall-through isn't the default. We can create fall through explicitly by using the fallthrough keyword however. Like:

switch 1 {
    case 1: fmt.Println("Hello")
    fallthrough
    case 2: fmt.Println("Gophers")
    fallthrough
    default: fmt.Println("Hi")
}

Output

Hello
Gophers
Hi

Fall-through was actually useful when multiple statements had the same block of statements to execute. However in Golang to counter the problem of not having fall-through, they introduced checking of multiple values in one case. Like:

switch v {
    case 1, 3, 5: fmt.Println("odd")
    case 2, 4, 6: fmt.Println("even")
    default: fmt.Prinln("None")
}

Now depending on the value of v, the program will print odd, even or none. This is a faster way than the use of fallthrough and also easier to write.

Nested

You have multiple conditional statements inside another conditional statement.

Your Turn

Take two variable, assign values to them in such a way that the first one is greater than the second one. Divide them (both must be integer). Now If your result is less than 5, find out whether the first number is greater than 10, and less than 20, else check if the difference between the number is divisible by 2 or not (If a number is divisible by another number, then the remainder between them is 0).

Take four variables and assign them with random letters and check how many vowels are there. If there are none, print an appropriate message

Loop

Sometimes as a programmer you want your statement to run over and over again until the condition gets satisfied. So today we shall learn about loops.

Now if you are coming from other languages you may think there are two or three (for older languages) types of loops. In Golang, there's only one. That is everyone's favorite for loop. For loop has different syntax, you can use the right one depending on what you need. The most basic one is the following:

var i
for initialize; check; increment/decrement/change in value {
    statements
}

So we first have to initialize it with some value. Then we have to check whether a condition is true so that the loop runs, and then change the value. The statements in a loop with runs continuously until the condition is false, when for the next iteration the condition becomes false the loop will not run. Suppose we want to print numbers from 0 to 10, we can easily do that using loops:

for i :=0; i<=10; i++ {
    fmt.Println(i)
}

Output

1
2
3
4
5
6
7
8
9
10

We can omit the initializing or the increment/decrement, but we have to initialize the value for the variable we use in loop, or else we will get an error. Also if we don't change the value of that variable the loop might run forever and never end generation some behavior we don't want.

var i = 0
for ; i < 10; i++ {
    fmt.Println(i)
}
var j = 0
for ; j<5; {
    fmt.Println(j++)
}

The first loop will print the values from 0 to 9 and the second loop from 0 to 5. Golang offer some syntactical sugar for us, if we don't initialize and increment/decrement as the same line as for loop declaration we can omit the semi colons. Please don't if we omit both, then only we can use this. This makes for loop very similar to while loop. We shall use this syntax of for loop when we don't know the number of iterations.

var i = 0
for i < 5 {
    fmt.Println(i++)
}

Another import function is the ranged for. It is used to get the index number and the uses with it. We shall understand better when we deal with string and arrays/slices.

for i, n :=range "Hello" {
    fmt.Println(i, " ", n)
}

Output:

0 "H"
1 "E"
2 "L"
3 "L"
4 "O"

We shall use more of this function in the future.

Nested

You can write a for loop inside another for loop.

for i := 0; i < 10; i ++ {
    for j := 0; j < 10; j ++ {
    } 
}

Your Turn

Try to print this patter

*
**
***
****

(Hint: You have to use Print and Println functions. Remember to use nested loops)

Struct

A structure or struct in Golang is a user-defined type that allows to group/combine items of possibly different types into a single type. Any real-world entity which has some set of properties/fields can be represented as a struct. This concept is generally compared with the classes in object-oriented programming. It can be termed as a lightweight class that does not support inheritance but supports composition.

Suppose you define a struct which contains your address, these shall be the variables inside it: House Name (string), Street Name (String), City (String), Pincode (int).

Let's define our struct. Till now we were declaring function inside our main function, but struct definitions are generally done outside main function:

package main

import "fmt"

type Address struct {
    houseName  string
    streetName  string
    city string
    pincode int
}
func main() {}

Now let's allocate values into it and print it. To allocate values we must always pass them in order, or else we can assign it as name:value. Example:

package main

import "fmt"

type Address struct {
  houseName string
  streetName string
  city string
  pincode int
}
func main() {
    var i = Address {
        houseName: "City Mall",
        streetName: "MG Road",
        city: "Delhi",
        pincode:110007
    }
    fmt.Println(i)
}

Output:

{City Mall MG Road Delhi 110007}

Another way is without using the name of the variable.

package main

import "fmt"

type Address struct {
    houseName string
    streetName string
    city string
    pincode int
}
func main(){
    var i = Address {
            "City Mall",
            "MG Road",
            "Delhi",
            110007
        }
    fmt.Println(i)
}

Output

{City Mall MG Road Delhi 110007}

Now what if you want to access any fields from the struct, how would you do so?

We can do so by using dot notation . followed by the name of the fields.

package main

import "fmt"

type Address struct {
    houseName string
    streetName string
    city string
    pincode int
}

func main() {
    var i = Address {
        houseName: "City Mall",
        streetName: "MG Road",
        city: "Delhi",
        pincode: 110007
    }
    fmt.Println(i.city)
}

Output :

Delhi

Your Turn

Make a struct called Birds, in it create 4 fields Name (string), CanFly (bool), isRare (bool), Age (int). In main function pass the name of a bird, pass true and false if it can fly or is it rare, and pass the age of it, and print the struct. If canFly or isRare is false then print an appropriate message. (Hint: Use if / else to check ).

Summary

In this post, we have learned how to declare constants, how to check conditions and perform operations, we have learned how to loop a set of statements depending on our need, and then we closed it all up with structures. We have also learned about different operators. In the next part, we shall learn more about structs, functions, data type and pointers.

Thanks for Reading

Follow us on Twitter.

Until we meet again,

Arindol Sarkar.

 
Share this