Getting "Hello world!" printed on the console.

"Hello world!" is the first basic program in every programming language. Let's write the Go hello world program by following these steps.

                      OUTPUT:
                      Hello world!
  1. In Go language, every program must start by declaring the package; here, the package is `main`.
  2. Next, import the `fmt` package to the program. The `import' keyword is used for importing packages to your program. Package 'fmt' has imported to implement formatted Inputs and Outputs with functions
  3. Now write the code in the 'main' function to print "Hello World!". The 'main' function is an entry point to the program, where the program starts.
  4. Using a single command, which is 'go run', we can compile and execute the program. Example :"go run hello_world.go"
  5. Using 'go build' command, we can create the executable file. Example : "go build hello_world.go" -> Output file "hello_world.exe"

Arithmetic Operators

    These operators are used for arithmetic and mathematical operations in Go.

Operator Name Description
+ Addition Adds to operands
- Subtraction Builds the sum of two numbers by subtracting them
* Multiplication Multiplies two values with each other
/ Division Divides two values
% Modulus Gets the remainder after an integer division
++ Increment It increases the integer value by one
-- Decrement It decreases the integer value by one
                      OUTPUT:
                      x + y = 28
                      x - y = 12
                      x * y = 160
                      x / y = 2
                      x % y = 4
                      x++ = 21
                      y-- = 7

Relational Operators

These operators are used to compare two values with each other.

Operator Name Description
== Equals to Returns true if x is equal to y
!= Not equal to Returns true if x is not equal y
< Lesser than Returns true if x is lesser than y
<= Lesser than Equal to Returns true if x is lesser than or equal to y
> Greater than Returns true if x is greater than y
>= Greater than Equal to Returns true if x is greater than or equal to y
                          OUTPUT:
                          false
                          true
                          true
                          true
                          false
                          false


Logical Operators

    The following logical operators are supported by the Go language.

    Operator Name Description
    && Logical AND Returns true if all conditions are true
    || Logical OR Returns true if at least one condition is true
    ! Logical NOT Inverts the result of the condition
                      OUTPUT:
                      false
                      true
                      true

Assignment Operators

These operators are used to assign values to variables.

Operator Name Description
= Simple Assignment Assigns the value to the variable
+= Add Assignment Adds the value to the current value of the variable
-= Subtract Assignment Subtracts the value to the current value of the variable
*= Multiply Assignment Multiplies the current value of the variable with the new value
/= Division Assignment Divides the current value of the variable by the new value
%= Modulus Assignment Takes modulus of the two values and assigns the result to left operand
                      OUTPUT:
                      20
                      30
                      -10
                      200
                      1
                      2


Bitwise Operators

    Go has the following bitwise operators to perform in bit level.

    Operator Name Description
    & AND Operator a&b - Returns a one in each bit position for which the corresponding bit of both operands are ones
    | OR Operator a|b - Returns a one in each bit position for which the corresponding bits of either or both operands are ones
    ^ XOR Operator a^b - Returns a one in each bit position for which the corresponding bits of either but not both operands are ones
    << Left Shift Operator a b - Shift a in binary representation b bits to the left, shifting in zeroes from the right
    >> Right Shift Operator a>>b - Shift a binary representation b bits to the right, discarding bits shifted off.
                      OUTPUT:
                      0
                      30
                      30
                      20
                      5


Variables

In this section, you can learn various ways to declare and initialize the variables.


Declaring variables

Using the var keyword, you can declare a variable followed by the variable name and data type.

 var i int 
 s = "String value"
Initializing variables

After declaring the variables, they can be initialized.

 i = 20 
 var s string

You can declare and Initialize a variable in a single line.

 var x int = 35

You can also omit the type when initializing the variable at the time of declaration and Go will guess the type of initialized variable.

 var t = true
 fmt.Println(t)
Short variable declaration

The var keyword can also be abandoned using the ":=" short variable declarator.

 y := 50
 z := "String value"
Declaring multiple variables

you can declare multiple variables in a single line of code.

 var q, r int = 10, 20
Variable Declaration Block

You can group variables for better readability and cleaner code.

 var ( 
 name = "James"
 age = 25
 )
                      OUTPUT:
                      20
                      String value
                      35
                      50
                      String value
                      10 20
                      James
                      25
                      true
                      0
                      false

Constants

    Constants can be declared using declaration blocks for better readability.

                      OUTPUT:
                      3.14159265359
                      500000
                      500000
                      500000
                      -0.9840610061203382

For-Loop

Go supports only one looping construct that is for-loop.

The most basic type using a single condition
                      OUTPUT:
                      0
                      1
                      2
                      3
                      4
                      5


  • A classic initial and a condition after for loop
  •                       OUTPUT:
                          0
                          1
                          2
                          3
                          4
                          5
                          6
                          7
                          8
                          9
                          10


  • An infinite loop is shown in this example. We can stop the loop by using the break statement
  •                       OUTPUT:
                          Hello World
                          Hello World
                          Hello World
                          Hello World
                          Hello World
                          Hello World
                          Hello World
                          Hello World
                          Hello World
                          Hello World
                          Hello World


  • We can iterate the loop, by using continue keyword
  •                       OUTPUT:
                            1
                            3
                            5
                            7
                            9


    If-Else

    In Go language, if statement can be used to execute a block of code according to a boolean expression

  • If statement executes the code only if the condition is true
  •                       OUTPUT:
                            true


  • When the boolean expression is false it is followed by else statement
  •                       OUTPUT:
                            x is greater than 5


  • If statement can also be chained using an optional else if.. else statement as the following example
  •                       OUTPUT:
                          B


  • In Go language, a short variable can be declared before the conditional expression in an if statement
  •                       OUTPUT:
                          15


    Switch

    A switch statement takes a specified expression and compares it against a list of multiple cases. Once the case matches the expression, it will execute the code block and it is a shorter way to write a sequence of if - else statements.

  • In switch, cases are analysed from top to bottom and stops when a case satisfy the condition after executing the relevant block of code. If no case matches the condition, the default case will be executed.
  •                       OUTPUT:
                            B 


  • Multiple cases can also execute a single code block as shown in the following code block
  •                       OUTPUT:
                            B,C


  • Switch also allows you to use conditional statements in your cases.
  •                       OUTPUT:
                            Smaller than 10


  • The switch statement also allows you to initialize the variable directly after the switch keyword which will only be accessible inside the statement.
  •                       OUTPUT:
                            Ten 


    Arrays

    Array is a collection of elements of a single type and It can hold multiple values at once. We can get the required value by using an index.
    Arrays have a fixed length and they can't be resized.

     Declaring an array and assigning values
                          OUTPUT:
                          10
                          2

     Initializing an array

    We can initialize an array with pre-defined values using an array literal. An array literal has the number of elements it will hold in square brackets,
    followed by the type of its elements.
    After that inside curly braces we can keep the initial values separated by commas of each element

                          OUTPUT:
                          [1 2 3 4 4]
                          [1 2 3 4 5]

     Initialize values for specific array elements
                          OUTPUT:
                          [0 10 15 0 0]

     Initializing an Array with ellipses

    Automatically detects array size based on the elements in the array expression using elliptical syntax.

                          OUTPUT:
                          5
                          [10 20 30 40 50]

     Copying an array

    There are two ways to copy an array. We can copy all its values or copy the reference of the array.

       copy values - copied arrays have the same values but are independent of the original array.
       reference  - changes in the original array are reflected in the copied array.

                          OUTPUT:
                          [1 2 3 4 5]
                          [1 2 3 4 5]
                          [1 2 3 4 5]
                          [1 2 3 4 5]
                          [1 2 3 4 5]

    Slices

    In Go language, a slice can be identified as a dynamically sized, flexible view of an underlying array.
    The sLice can grow or shrink within the range of underlying array. If Like in arrays we cannot store different type of elements in the same slice.

    Creating a slice
                          OUTPUT:
                          slice
                          length : 10
                          capacity : 20
                          length : 4
                          capacity : 4
                          [10 20 30 40]
                          length : 4
                          capacity : 49
                          [0 0 0 0]

    Append Elements to the slice

    The built-in append function appends elements to the end of a slice. If the underlying array doesn't have enough capacity to append new elements, a new underlying array will be allocated and the append function will return the updated slice.

                          OUTPUT:
                          [0]
                          length : 1
                          capacity : 2
                          [0 10]
                          length : 2
                          capacity : 2
                          [0 10 20 30 40]
                          length : 5
                          capacity : 8

    Access elements of a slice

    We can use the indices to access the values stored in the slice like with arrays.
    The format of a slice is defined by two indices, a low and high bound, separated by a colon:

    a[low : high]

                          OUTPUT:
                          1
                          3
                          s1 -> length = 6  capacity = 6  slice = [1 3 6 10 15 21]
                          s1[1:5] -->  [3 6 10 15]
                          s1[ :4] -->  [1 3 6 10]
                          s1[3: ] -->  [10 15 21]
                          s2 -> length = 0  capacity = 5  slice = []
                          s3 -> length = 4  capacity = 6  slice = [1 3 6 10]
                          s4 -> length = 5  capacity = 5  slice = [3 6 10 15 21]
                          s5 -> length = 3  capacity = 4  slice = [6 10 15]

    Change element values in a slice

    Elements can be changed by pointing to a specific index and setting a new value.


    Copy function

    Slices can be copied using the build-in copy() function.

                          OUTPUT:
                          [6 7 8 9 10]

    Maps

    A map is a random collection of key/value pairs. Each key in a map is unique. Using the key, the value can be quickly retrieved from the map object. Maps can be created using built-in make function.
    A map can be declared and initialized using multiple techniques.

    • Declaring map and then adding objects.
    • Initializing the map using some default values.
    • Declaring the map using the make function
                          OUTPUT:
                          map[]
                          map[James:20 Rob:25]
                          map[Arthur:30 Peter:25]

    Accessing, Adding, Updating and Deleting keys/values from a map.
    • Accessing and manipulating a map is like an array.
    • Values can also be accessed by entering the key in squared brackets.
    • Adding a new item can be done by assigning a new key to the map and giving a value to the variable.
    • The update is the same, but you can use the existing key to update instead of a new key.
    • Delete functions are used to delete values and the map and key can be passed as active arguments. The function will then delete the item in the map instance itself and therefore not have a return value.
                          OUTPUT:
                          James
                          map[C001:James C002:Arthur C003:Rob C004:Peter C005:Laura]
                          map[C001:Tom C002:Arthur C003:Rob C004:Peter C005:Laura]
                          map[C001:Tom C003:Rob C004:Peter C005:Laura]
                        

    Iterating over a map

    For loop uses the range keyword to quickly reset across a map and retrieve keys and value variables. A map is an unordered collection and there will be no possibility to predict in which order keys/values will be returned.

                          OUTPUT:
                          C003 : Van
                          C004 : Dennis
                          C001 : Rob
                          C002 : James
                          C003 : Van

    Range

    In Go Language, Range can be used to iterate over strings, arrays, slices, maps and channels. For each iteration, two values are returned. The first is the index, and the second is a copy of the element at that index.

                          OUTPUT:
                          Index 0 :	value :golang
                          Index 1 :	value :0example
                          Index 2 :	value :wixis360
                          sum :23940 0
                          1 e
                          2 x
                          3 a
                          4 m
                          5 p
                          6 l
                          7 e
                          Sri Lanka  -  LKR
                          United States  -  USD
                          United Kingdom  -  Sterling Pound
                          United States  -  USD
                          United Kingdom  -  Sterling Pound
                          Sri Lanka  -  LKR
                          on
                          off

    Functions

    A function is a block of codes or a group of statements that perform a task. Functions can be declared using the func keyword followed by the function name, a pair of parentheses and a code block containing the functionality. The function name can be used to refer to the function.

                          OUTPUT:
                          Hello World!

    Function Parameters

    Call By Value
    When parameters passing, values of parameters are copied to function’s new parameters and the two types of parameters are stored in different memory locations. So any changes made inside functions are not reflected in actual parameters of the caller.

                          OUTPUT:
                          Hello World!
                          30
                          Inside the change func: x = 100 AND y = 200
                          x = 10 AND y = 20

    Returning Values

    Returning values from a function is another essential concept and can be done by providing a return type after the first pair of parentheses.

                          OUTPUT:
                          Sum : 50

    Named Return Values

    We can define functions with named return types in round brackets after the function parameters.

                          OUTPUT:
                          2 11 101 1001

    Functions with multiple return values

    Go language allows to return multiple values from a function.

                          OUTPUT:
                          Sum:  15
                          Multiply 50

    Passing addresses to function

    Pass the address of a variable to a function and modify it with the reference in the function.

                          OUTPUT:
                          Before: 20 25
                          After: 25 35

    Assigning function to a variable

    Anonymous functions allow you to assign a function to variable.

                          OUTPUT:
                          15

    Closure functions

    A Closure function is an anonymous function.A function which has no name is called an anonymous function. where you access outside variable.A closure refers its reference variable outside the function body.

                          OUTPUT:
                          15

    This function addValues returns another function, which we define anonymously in the body of addValues. The returned function closes over the variable z to form a closure

                          OUTPUT:
                          15

    Variadic Functions

    A variadic function can take an arbitrary number of arguments.

                          OUTPUT:
                          Rob
                          James
                          Arthur

    Deferred function

    Defer is unique Go statement that schedules a function call to be run after the function completes.

    >
                          OUTPUT:
                          First Function
                          Second Function

    Pointers

    A pointer is a variable which holds the memory address of another variable
    The type *p is a pointer to a p value. The &p syntax gives the memory address of p
    The zero value of a pointer is nil.

                          OUTPUT:
                          value of x at the beginning: 1
                          after calling func zeroValue, x :  1
                          After calling func zeroPointer, x : 0
                          Pointer address :  0xc00000a098

    Structs

    Structure is a collection of data fields with predefined types that can define your own data type, which is similar to a class in java.
    All data fields in a structure can be expressed using a predefined type.
    Structures further enhance the modularity of our application and help define the structure of complex objects. They can be sent to do tasks or used in other ways

    Declaring a struct

     Structures are declared using both the type declaration before the real name and the structural declaration after the name. The struct contains multiple fields with their defined datatype.

    Creating a struct

    There are multiple ways to create a structure. Here is a list of such common design processes.

    • Declaring a variable with the struct as the datatype without initializing it.
    • Creating an instance using struct literate.
    • Creating an instance using the new keyword.
    • Using the pointer address operator to create a new instance.
                          OUTPUT:
                          {Rob 40}
                          {James 35}
                          &{Arthur 35}
                          &{Ben 25}
                        
    Comparing struct instances

    "==" operator or the reflect.DeepEqual() method is used to compare two instances of the same structure with each other.
    If all the values are the same then `true` will be returned.

                          OUTPUT:
                          &{Namal 25}
                          &{Kasun 30}
                          false
                          false

    Copying a struct

    Here we are copying a structure, when we need a second case, with values

                          OUTPUT:
                          &{James 25}
                          &{Rob 25}

    Methods

    Even though Go language doesn't have classes, we can define methods on types. A method is a function which contains a receiver argument.

                          OUTPUT:
                          Student ID :  st001
                          Student Name :  James
                          Email :  james@gmail.com
                          Contact Number:  41560195
                          arthur@gmail.com

    Interface

    A set of methods signatures is defined by an interface in golang.

    Defining an Interface

    You can define an interface by putting `interface` keyword after `type` and `name` of the interface.

    The User interface defines a single method signature called PrintName(). Any type that implements the PrintName() function will therefore now satisfy the User interface


    Implementing the Interface

    When implementing an interface in your struct you will not need to explicitly specify the interface that is implemented.
    Go will automatically determine if the struct implements the interface by checking, if it implements the method signatures defined in the interface

                          OUTPUT:
                          User Id:  C001
                          User Name:Rob
                          Car Name: Vega

    Errors

    Go language does not have an exception handling mechanism like try-catch in Java. So we cannot throw an exception in Go. Go has a different approach for handling errors which is called defer-panic-and-recover mechanism.

    For most go functions and methods, errors are returned last as a normal return value and have type error, a built-in interface. The error built-in interface type is the conventional interface for representing an error condition, with the nil value representing no error.

    An idiomatic way to handle an error is to check the last return value of a function call and check for the nil condition.

    Example 1:
    OUTPUT : 2021/02/23 19:03:44 open 00example.txt: The system cannot find the file specified.

    Example 2:

    errors.New function can create a new Error and it returns an error that formats as the given text.

                          OUTPUT:
                          8 / 4 = 2
                          2021/02/07 05:35:41 can not be divided by 0

    Example 3:

    We can create a new error with a formatted error message by using fmt.Errorf() function.

                          OUTPUT:
                          SquareRoot of 4.00 = 2.00
                          -4.00 is less than zero

    Example 4:

    We can implement the predeclared error interface to define a customer error type.

                  OUTPUT:
                  remaining balance : 800.00
                  2021/03/07 05:49:25 balance :150.00 -- amount :2000.00 -- msg: Invalid amount or balance

    Concurrency

    Concurrency is the ability of independently executing multiple tasks at the same time. But it is not parallelism.
    Golang has 2 built-in concurrency constructs: goroutines & channels

    Goroutines

    Goroutine is a function that executes concurrently, managed by go runtime. You can see it as a lightweight thread. To invoke goroutine you should add `go` keyword before calling the function.

    Example 1
                          OUTPUT:
                          counting : 0
                          counting : 1
                          counting : 2
                          counting : 3
                          counting : 4
                          counting : 5
                          counting : 6
                          counting : 7
                          counting : 8
                          counting : 9

    After running the above code when the main function executes the main goroutine starts running
    Then due to Sleep method the main Goroutine sleeps for 3 seconds.
    In between 3 seconds, the new Goroutine executes displaying the counting numbers on the console.
    When the main method returns after the duration given in the sleep method, the program exits and takes the counting function down with it.


    Example 2
                          OUTPUT:
                          Direct 0
                          Direct 1
                          GoRoutine 0
                          GoRoutine 1
                          GoRoutine 2
                          GoRoutine 3
                          GoRoutine 4
                          Direct 2
                          Direct 3
                          anonymous
                          Direct 4
                          back to main

    Invoking print function in a goroutine by using go keyword. secondly, calling print function the usual way running it synchronously.
    We can use goroutine for an anonymous function as well. After executing the code we can see that the functions are running asynchronously in separate goroutines.


    Channels

    Channels can be identified as pipes that connect goroutines through which you can send and receive values with the channel operator <-

                          OUTPUT:
                          0xc000048060 0xc0000480c0
                          123
                          15

    When the program is executed value is passed from one goroutine to other through the channel successfully. By default, sends and receives block until the other side is ready.
    Channels allow goroutines to synchronize without explicit locks or condition variables.


    Channel Buffering

    By default channels can accept a single send(<-) if there is a receive. They are unbuffered. Buffered channels can store multiple values without a corresponding receiver for those values.

                          OUTPUT:
                          Go
                          Lang
                          Oexample

    Channel Synchronization

    Channels can be used to synchronize the execution of goroutines. A Channel can make a goroutine wait until the its execution process is finished.
    You can use this, when you need to finish a goroutine before you need to start another one.

                          OUTPUT:
                          Doing task 1...finished
                          Doing task 2...finished
                        

    Channel Directions

    By default channels are bidirectional. This means you can both send and receive data using the channel. But you can change the channel direction as receive-only or send-only according to the situation.

                          var bi_direc_chn        chan string   	 -- can receive, send data.
                          var receive_only_chn    <-chan string      -- can receive only
                          var send_only_chn       chan<- string  	 -- can send only.
                          OUTPUT:
                          hello, this is
                          0example.com

    Select

    Golang select statement is similar to the switch statement, which lets a goroutine wait on multiple channel operations.
    The select statement blocks as a whole unit, until one of the operations finished

    Example 1:
                          OUTPUT:
                          Calling method 2

    Values will return to the two channels after passing the time duration spent in the relevant method. The output depends on the time taken to execute the relevant methods.
    Therefore, after 5 seconds the case `msg2` will be executed.


    Example 2:

    The default case will be executed if all other cases are blocked.

                          OUTPUT:
                          www.0example.com

    Default case is used to protect the select statement from blocking. If the Select has no default case, the select statement waits until at least one case can be executed.
    When there is a default case, it is executed if none of other cases are ready to proceed.


    Timeouts

    We always try to make Real life applications time sensitive. Therefore, Timeouts are necessary to ensure tasks that run overdue do not consume the resources that might be needed by other components of our application. We can easily implement timeouts by using channels and select.

                          OUTPUT:
                          ABC running.. :)
                          XYZ timeout.! :(

    In the example above,Two functions funcABC and funcXYZ are executed in goroutines which take 2s and 6s to complete respectively.
    Select statements are implementing timeouts res := <-c1 and res := <-c2 await for results to return. and <-time.After(3 * time.Second) awaits to send the timeout message 6 seconds.
    If the channel recieves a value before the timeout time then the result is printed( ex: funcABC) If it is timeout before receiving a value then the timeout value is printed (ex: funcXYZ)


    Non-Blocking Channel Operations

    By default, reading and writing operations on channels are blocking. By using default case with select , we can acquire non-blocking send, receive operations and unblocked multi way selects.

    Example 1:

    Pushing a value to a channel which is already full is blocked until the value inside the channel is consumed by another goroutine.

                          OUTPUT:
                          An error called deadlock occurred as it is blocked after 3 values are queued to the channel.

    We can use select statement with default case to avoid this issue


    Example 2:

    By using the default case we can avoid the deadlock error.

                          OUTPUT:
                          message sent to channel successfully :)
                          message sent to channel successfully :)
                          message sent to channel successfully :)
                          Channel is full. :(
                          Channel is full. :(

    Example 3:

    When values are sent to an unbuffered channel the deadlock error occurred. We can avoid this issue by using default case

                          OUTPUT:Status not set

    Example 4:

    Using select with default case we can receive a value from a channel if a value is available. If there is no value the default case will be executed.

                          OUTPUT:no status received

    Closing Channels

    Closing the channel signals to consumers of the channel that no more values will be sent on this channel.

                          OUTPUT:
                          3
                          6
                          9

    After closing channel you can still read the values but can't send data. If you try to send data after closing the channel it will throw an error message.


    Range and Close

    We can use range syntax on channels to iterate over received values.
    You should close the buffered channel before iterate over values.

                          OUTPUT:
                          3
                          6
                          9

    Here, range iterates over received elements from the channel and stops iterating because the channel is closed after receiving 3 values.


    Timers

    Timer is a built in feature in go that can be used to fire some task after a period of time in the future.
    NewTimer function creates a new Timer that will send the current time on its channel after duration which was passed as an argument.
    NewTimer(d).C is equivalent to the time.After(d) function.
    If the timer is no longer needed we can use NewTimer instead and call Timer.Stop()
    It will prevent the timer from firing and return true if the call stop the timer.

                          OUTPUT:
                          timer THREE terminated..!
                          timer ONE executed.. :)
                          timer TWO executed.. :)

    Tickers

    Tickers can execute a certain peace of code repeatedly on a regular interval of time.

    Timers - use for one time task firing in a future time.
    Tickers -use for repeated tasks at regular time intervals.

    Example 1:
                          OUTPUT:
                          Tick at... 2021-03-05 04:30:39.5639206 +0530 +0530 m=+0.552284101
                          Tick at... 2021-03-05 04:30:40.1138485 +0530 +0530 m=+1.102212001
                          Tick at... 2021-03-05 04:30:40.6642701 +0530 +0530 m=+1.652633601

    As shown in the example you can use tick function combined with range to repeat some task.
    Tick is a wrapper for NewTicker function which provides access to the ticking channel.
    Tick is useful for clients that have no need to shut down the Ticker.
    But ticker cannot be recovered by garbage collector as there is no way to shut down the ticker.


    Example 2:

    Tickers can be stopped like timers using stop() function when you are using newTicker function.

                          OUTPUT:
                          time :  2021-03-05 04:41:19.7884087 +0530 +0530 m=+0.502138901
                          time :  2021-03-05 04:41:20.289211 +0530 +0530 m=+1.002941201
                          time :  2021-03-05 04:41:20.7889216 +0530 +0530 m=+1.502651801
                          time :  2021-03-05 04:41:21.2884459 +0530 +0530 m=+2.002176101
                          ticker stopped..!

    The NewTicker() function returns a new Ticker containing a channel which send time according to the duration argument.
    The duration must be greater than zero, if not, the ticker will panic.
    Unlike NewTicker, Tick will return nil if duration is <= 0.


    Worker Pools

    This example illustrates how to implement a worker pool using goroutines and channels

                          OUTPUT:
                          Worker: 2 Started Job :  1
                          Worker: 1 Started Job :  2
                          Worker: 1 Finished Job :  2
    
                          Worker: 1 Started Job :  3
                          Worker: 2 Finished Job :  1
    
                          Worker: 2 Started Job :  4
                          Worker: 2 Finished Job :  4
    
                          Worker: 1 Finished Job :  3

    After running the programme we can see, even though it takes about 4 seconds to complete the 4 tasks, it only took about 2 seconds to finish as the workers did the tasks concurrently


    Wait Groups

    A waitgroup waits until the goroutines inside the waitgroup have successfully executed. A waitgroup contains three functions.

    1. Add(int) - Add adds integer value to the WaitGroup counter. If the counter becomes zero, all goroutines blocked on Wait are released.
    2. Done() - Done decreases the waitgroup counter by one.
    3. Wait() - Wait blocks until the WaitGroup counter is zero.
                          OUTPUT:
                          http://google.com website is running...
                          https://tour.golang.org/ website is running...
                          https://play.golang.org/ website is running...
                          https://golang.org website is running...
                          http://0example.com website is running...

    First we create a waitgroup and add goroutines to it When a goroutine is added it will increment the waitgroup counter.
    We call function Add() on our WaitGroup to set the number of goroutines we want to wait for, and then, we call function Done() at the end of function to indicate the end of goroutine's execution


    Atomic Counters

    We communicate with channels to manage state in go.
    Atomic counters also can be utilized to manage state and avoid race conditions in go.
    Atomic counters can be accessed by multiple goroutines.
    They are more primitive than other synchronization techniques and implemented directly at hardware level.
    Package `atomic` provides low-level atomic memory primitives useful for implementing synchronization algorithms.

                          OUTPUT:
                          3
                          4
                          5
                          6
                          2
                          1
                          7
                          final value of the counter : 7

    Mutexes

    Mutex or Mutual Exclusion lock is a is a synchronization technique which can be used to synchronize access to state and safely access data across multiple goroutines.
    We can define a block of code to be executed in a mutex by surrounding it with a call to Lock and Unlock The zero value for a Mutex is an unlocked mutex.
    A Mutex must not be copied after first use.

                          OUTPUT:
                          Bar: 0 counter: 1
                          Foo: 0 counter: 2
                          Foo: 1 counter: 3
                          Bar: 1 counter: 4
                          Bar: 2 counter: 5
                          Foo: 2 counter: 6
                          Foo: 3 counter: 7
                          Bar: 3 counter: 8
                          Bar: 4 counter: 9
                          Foo: 4 counter: 10
                          Foo: 5 counter: 11
                          Bar: 5 counter: 12
                          Bar: 6 counter: 13
                          Foo: 6 counter: 14
                          Foo: 7 counter: 15
                          Bar: 7 counter: 16
                          Bar: 8 counter: 17
                          Foo: 8 counter: 18
                          Foo: 9 counter: 19
                          Bar: 9 counter: 20
                          Counter :  20

    Sorting

    Package sort provides primitives for sorting slices and user-defined collections. Here is an example for sorting slices.

                          OUTPUT:
                          Integers sorted :  [-6 3 9 12]
                          Float sorted :  [-1.9 0.3 2.7 5.8]
                          Strings Sorted :  [apple mango orange]
                          Is integers sorted :  true
                          [12 9 3 -6]

    Sorting by Functions

    We can also implement our own sorting schema, by implementing the len,less,swap functions in the sort interface.
    For an example, if we wanted to sort some strings not in an alphabetical order instead considering their lengths we can use the sort interface.
    The length of the collection is returned by less function. `Less` receives two integers which indicate indices from the collection.
    After less method is called swap method makes the necessary changes.

                          OUTPUT:
                          [{Rob 21} {James 15} {Dennis 20}]
                          [{James 15} {Dennis 20} {Rob 21}]

    String Formatting

    printf in go is similar to the C language printf. The format 'verbs' are derived from C's but are simpler.
    Go provides some verbs to format the strings. Here, are some verbs.

                          OUTPUT:
                          {3 6}
                          {a:3 b:6}
                          main.value{a:3, b:6}
                          main.value
                          %
                          false
                          1000
                          A
                          26
                          24
                          0o24
                          "\"string\""
                          6578616d706c65
                          0xc00000a0b0
                          12.11

    Regular Expressions

    A regular expression is a sequence of characters use for searching and replacing text and more advanced text manipulation.
    In go language, package regexp implements regular expression search.

                          OUTPUT:
                          le
    
                          [1 3]
                          [0example exampl]
                          [0 8 1 7]
                          [el ep en]

    JSON

    Go has built-in support for JSON (JavaScript Object Notation) encoding and decoding and it also supports custom data types.

    We use the Marshal function to convert go data types into JSON format.

    Syntax: func Marshal(v interface{}) ([]byte, error)

    We use Unmarshal function to decode JSON data type.

    Syntax: func Unmarshal(data []byte, v interface{}) error
    Example 1:
                          OUTPUT:
                          true
                          28
                          22.7
                          "0example"
                          ["0example","golang","google"]
                          {"customer":"user","manager":"admin"}
                          map[customer:user manager:admin]

    Example 2:
                          OUTPUT:
                          {"SID":"S001","Name":"James Arthur","Email":"james.arthur@gmail.com","Contact":5126356}
                          S001 James Arthur james.arthur@gmail.com 5126356
                          {"id":"S001","schoolName":"Golang College","location":"Google"}
                          S001 Golang College Google

    XML

    Go has built-in support for XML by implementing the encoding.xml package.

                          OUTPUT:
                          <student id="S001">
                             <name>James</name>
                             <email>james@gmail.com</email>
                             <contact>12234344</contact>
                           </student>
                          <?xml version="1.0" encoding="UTF-8"?>
                           <student id="S001">
                             <name>James</name>
                             <email>james@gmail.com</email>
                             <contact>12234344</contact>
                           </student>
                          Student id=S001, name=James, email=james@gmail.com, contact:=12234344
                           <nesting>
                             <parent>
                               <child>
                                 <student id="S001">
                                   <name>James</name>
                                   <email>james@gmail.com</email>
                                   <contact>12234344</contact>
                                 </student>
                                 <student id="S002">
                                   <name>Arthur</name>
                                   <email>arthur@gmail.com</email>
                                   <contact>22234344</contact>
                                 </student>
                               </child>
                             </parent>
                           </nesting>
    ;

    Time

    In Go language, package time provides functionality for measuring and displaying time.
    Go supports for various types of time manipulations.
    We can built a time object by using Date function provided in the time package.
    There are functions like year(), month(), day() in the time package.

                          OUTPUT:
                          Current Time :  2021-03-05 06:47:46.1728896 +0530 +0530 m=+0.001995101
                          MM-DD-YYYY	: 03-05-2021
                          YYYY.MM.DD	: 2021.03.05 06:47:46
                          YYYY:MM:DD {Character} : 2021:03:05
                          YYYY-MM-DD hh:mm:ss: 2021-03-05 06:47:46
                          Time with MicroSeconds: 2021-03-05 06:47:46.172889
                          ShortNum Month :  2021-3-05
                          LongMonth :  2021-March-05
                          ShortMonth :  2021-Mar-05
                          LongWeekDay :  2021-03-05 06:47:46 Friday
                          ShortWeek Day :  2021-03-05 Fri
                          Past Date Time : 2012-12-12 12:12:13.212121212 +0000 UTC
                          Year of pastDateTime : 2012
                          Month of pastDateTime : December
                          Date of pastDateTime : 12
                          Hour of pastDateTime : 12
                          Whether pastDateTime before current time : true
                          Whether pastDateTime after current time : false
                          Whether pastDateTime equals to current time : false
                          72109h5m32.960768388s
                          Duration in hours :  72109.09248910233
                          Duration in Minutes :  4.32654554934614e+06
                          Duration in Seconds :  2.595927329607684e+08

    Epoch

    In Go language, we can use time.Now() function to get current time and Unix() function to convert it into an epoch timestamp

                          OUTPUT:
                          current time : 2021-03-05 06:54:28.6973288 +0530 +0530 m=+0.001992801
                          epoch time stamp in seconds : 1614907468
                          Convert epoch to relevant time : 2021-03-05 06:54:28 +0530 +0530
                          epoch timestamp in nanoseconds : 1614907468697328800
                          convert epoch to relevant time : 2021-03-05 06:54:28.6973288 +0530 +0530

    Random Numbers

    In Go language, we can use package math/rand for generating pseudorandom numbers.
    It produces a deterministic sequence of values, each time program runs because it uses default shared Source.
    If you need a different behaviour for each run, you have to use the seed function to initialize the default Source.

                          OUTPUT:
                          Random Integer : 1
                          Random float of range[0.0-1.0) : 0.9405090880450124
                          Random float of range[10.0-20.0) : 16.645600532184904
                          Random number with different seed each run : 1
                          same seed : 5	7	8	0	3
                          same seed : 5	7	8	0	3

    Number Parsing

    In Go language, we can use package strconv for conversion of strings to numbers. Here are some examples for string conversion.

                          OUTPUT:
                          123
                          1253
                          strconv.Atoi: parsing "golang": invalid syntax
                          499
                          7777
                          3.14159

    URL Parsing

    URL is an address which can be used to access a given unique resource on the web. URL has a scheme, authentication info, host, port, path, query params, query patterns and query fragment. In this section you can see how to parse URLs in Go language. Package url parses URLs and implements query escaping.

                          OUTPUT:
                          API server listening at: [::]:11169
                          Scheme : http
                          User and Password : user:pass
                          Username :  user
                          Password : pass
                          Host and Port : 0example.com:8000
                          Host : 0example.com
                          Port : 8000
                          Path : /docs/books/tutorial/index
                          Fragment : DOWNLOADING
                          Query param name and value : key2=networking
                          Param Map : map[key2:[networking]]
                          Key Value : networking

    //Go language has built in support for base64 encoding. //Encoding means converting information from one form to another, and can be converted to the previous form //using the same algorithm that encoded it. //The base64 encoding uses a symbol table of 64 characters to encode the data into a string containing those symbols. //The 64 characters are A-Z, a-z, 0-9, +, /, =

    Base64 Encoding

    Go language has built in support for base64 encoding. Encoding means converting information from one form to another, and can be converted to the previous form using the same algorithm that encoded it.
    The base64 encoding uses a symbol table of 64 characters to encode the data into a string containing those symbols. The 64 characters are A-Z, a-z, 0-9, +, /, =

                          OUTPUT:
                          Encoded Data : aHR0cHM6Ly93d3cuMGV4YW1wbGUuY29t
                          Decoded Data : https://www.0example.com

    Reading Files

    In Go Language we can use the ReadFile() function of the ioutil package to read data from a file. We can read text and binary files using this function. When there is large files to read we can convert them into byte slices and read them.

                          txt file:
                          file path :path/student.txt
                          file content : James Arthur    james@gmail.com    0128313121
                          OUTPUT:
                          James Arthur    james@gmail.com    0128313121No of bytes read : 14
                          Data read from the file : James Arthur
                          6 bytes from position 6 : Arthur
                          3 bytes from 6 to : Art
                          3 bytes: hur

    Writing Files

    Go language supports for opening and writing files on the hard drive.

                          OUTPUT:
                          Number of bytes written: 6
                          Number of bytes written: 5
                          Completed.

    File Paths

    In Go language, package filepath implements utility routines for manipulating filename paths in a way compatible with the target operating system-defined file paths.

                          Example :
                          On Linux :	/home/John
                          On Windows :\Users\Rob
                          OUTPUT:
                          path : 0example\golang\filepath.go
                          golang\package\test.go
                          package\test.go
                          Dir of path(0example\golang\filepath.go): 0example\golang
                          Base of path(0example\golang\filepath.go): filepath.go
                          Splitting of path(0example\golang\filepath.go): 0example\golang\ filepath.go
                          false
                          true
                          .go
                          golang
                          xy\file
                          ..\ef\rs\file

    Directories

    A directory is a unit in a computer's file system for storing and locating files.

                          OUTPUT:
                         Listing temp-dir/parent-dir
                             child-dir true
                             myfile2.txt false
                             myfile3.txt false
                         Visiting temp-dir
                            temp-dir true
                            temp-dir\myfile.txt false
                            temp-dir\parent-dir true
                            temp-dir\parent-dir\child-dir true
                            temp-dir\parent-dir\child-dir\myfile4.txt false
                            temp-dir\parent-dir\myfile2.txt false
                            temp-dir\parent-dir\myfile3.txt false

    Temporary Files and Directories

    Temporary files and directories are useful when we don't need data after the program execution

                          OUTPUT:
                          img-dir\golang-676532635.png
                          www.0example.com
                          Temp dir name: = C:\Users\alpha\AppData\Local\Temp\sampledir267405374

    Environment Variables

    Environment variable is a dynamic key-value pair on the operating system. Environment variables can be used to configure behaviours of the running processes on the operating system. In Go language, we can use `os` package to work with environment variables. The `go` command uses the default setting, if an environment variable is not set.

                          OUTPUT:
                          WIXIS_USER: gopher
                          WIXIS_HOST:
    
    
                          APPDATA
                          GOPATH
                          GOROOT
                          HOMEDRIVE
                          HOMEPATH
                          WIXIS_USER

    Golang Web Service

    Web service is a standardized medium to propagate communication between the client and server applications on the World Wide Web.

    Web services provide a common platform that allows multiple applications built on various programming languages to have the ability to communicate with each other.

    From the above example, we created a simple program for the purpose of the web service.

                          OUTPUT:
                          on webpage: 0example!
                          on console: powered by Wixis360
                        

    MQTT Server

    MQTT stands for Message Queuing Telemetry Transport.It is a lightweight publish and subscribe system where you can publish and receive messages as a client. MQTT is a simple messaging protocol, designed for constrained devices with low-bandwidth.

    In this program we 'll be creating a shell to publish messages on a particular topic using Mosquitto mqtt broker, and another application to subscribe to a topic and print incoming messages on the terminal.


    String matching

    String matching algorithms, sometimes called string searching algorithms are used to find a place where one or several strings(also called patterns) are found within a larger string or text. There are so many types of string matching algorithms. One of them is shown here.

    Here, the first function finds whether the letters and the length are the same in the second input string as the first input string. If so, it will return true and if not it will return false.

                          OUTPUT:
                          First string input:-   S A M A
                          Second-string input:-  S A M A
    
                          Boolean output  =====> True
                          First string input :-   M A L A
                          Second string input :-  M A L I
                          Boolean output  =====> False

    Database connection

    This example will explain to you how to create a database connection using the Go language. For any application, it is very important to store the database on a server for easy data access.