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:
- Arithmetic Operator.
- Relational Operator.
- Logical Operator.
- Bitwise Operator.
- Assignment Operator.
- 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).
- Addition: The
+
operator is to add two operand. - Subtraction: The
-
operator is to subtract two operand. - Multiplication: The
*
operator is to multiply two operand. - Division: The
\
operator is to divide two operand. Dividing two integer returns an integer. - 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:
==
: Is equality operator, it is used to check whether the left and right-hand side operands are equal. It returnstrue
if both are equal or else returnsfalse
.
Output:fmt.Println(3 == 3) fmt.Println(4 == 5) fmt.Println(2 == 2.0)
true false true
!=
: Is the not equal to. It is used to check whether the two operands are different. It returnstrue
if they are not equal and returnsfalse
if they were.!
is the not operator.
Output:fmt.Println(3 != 4) fmt.Println(5 != 10 / 2) fmt.Println(3.14 != 22 / 7)
true false true
>
: Known as greater than operator. It is used to check whether the left-hand is greater than the right-hand side. It returnstrue
if the left-hand side operand is greater than the right otherwise it returnsfalse
.
Output:fmt.Println(4 > 5) fmt.Println(5 > 5) fmt.Println(6 > 5)
false false true
>=
: 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 returnstrue
if the left operand is greater than or equal to the right-hand side or else returnsfalse
.
Output:fmt.Println(4 >= 5) fmt.Println(5 >= 5) fmt.Println(6 >= 5)
false true true
<
: Known as lesser than operator. It returnstrue
if left-hand side is lesser than the right-hand side, or else returnsfalse
.fmt.Println(4 < 5) fmt.Println(5 < 5) fmt.Println(6 < 5)
Output:
true false false
<=
: Known as the lesser than equal to operator. It returnstrue
if the left-hand side is lesser than or equal to the right-hand side, or else returnsfalse
.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:
&&
: The logical and operator returnstrue
if all the conditions that are being joined by it aretrue
.
Output :fmt.Println(true && false) fmt.Println(6 > 5 && 10 > 9)
false true
||
: The logical or operator returnstrue
if any of the conditions that it joins aretrue
.
Output:fmt.Println(true || false) fmt.Println(6 > 5 || 10 > 9)
true true
!
: 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:
&
(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.|
(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.^
(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.<<
(left shift): Takes two numbers, left shifts the bits of the first operand, the second operand specifies the number of places to shift.>>
(right shift): Takes two numbers, right shifts the bits of the first operand, the second operand specifies the number of places to shift.&^
(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:
=
: Known as equals to. It assigns the values at the right to the left-hand side.a +=
: Other form of writinga = a + ...
, where a is a variable.a -=
: Other form of writinga = a - ...
, where a is a variable.a *=
: Other form of writinga = a * ...
, where a is a variable.a /=
: Other form of writinga = a / ...
, where a is a variable.a %=
: Other form of writinga = a % ...
, where a is a variable.a &=
: Other form of writinga = a & ...
, where a is a variable.a ^=
: Other form of writinga = a ^ ...
, where a is a variable.a |=
: Other form of writinga = 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
- If / Else
- 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 range
d 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.