Goroutines

Goroutines

In this tutorial, we are going to discuss about how concurrency is achieved in Go language using Goroutines. Go language provides a special feature known as a Goroutines.

A Goroutine is a function or method which executes independently and simultaneously in connection with any other Goroutines present in your program. Or in other words, every concurrently executing activity in Go language is known as a Goroutines.

You can consider a Goroutine like a light weighted thread. The cost of creating Goroutines is very small as compared to the thread.

Every program contains at least a single Goroutine and that Goroutine is known as the main Goroutine.

All the Goroutines are working under the main Goroutines if the main Goroutine terminated, then all the Goroutine present in the program also terminated. Goroutine always works in the background.

Goroutine vs Thread
Goroutines
How to start a Goroutine?

You can create your own Goroutine simply by using go keyword as a prefixing to the function or method call as shown in the below syntax:

func name(){ 
   // statements 
}

// using go keyword as the prefix of your function call 
go name()
package main

import (
    "fmt"
)

func hello() {
    fmt.Println("Hello world")
}

func main() {
    go hello()
    fmt.Println("Hello this is main function")
}

Output

Hello this is main function

Run in playground

In the above program, go hello() starts a new Goroutine. Now the hello() function will run concurrently along with the main() function. The main function runs in its own Goroutine and its called the main Goroutine.

Run this program and you will have a surprise..!!

This program only outputs the text Hello this is main function. What happened to the Goroutine we started? We need to understand two main properties of go routines to understand why this happens.

When a new Goroutine is started, the goroutine call returns immediately. Unlike functions, the control does not wait for the Goroutine to finish executing. The control returns immediately to the next line of code after the Goroutine call and any return values from the Goroutine are ignored.

The main Goroutine should be running for any other Goroutines to run. If the main Goroutine terminates then the program will be terminated and no other Goroutine will run.

I guess now you will be able to understand why our Goroutine did not run.

After the call to go hello() in above program, the control returned immediately to the next line of code without waiting for the hello goroutine to finish and printed main function.

Then the main Goroutine terminated since there is no other code to execute and hence the hello Goroutine did not get a chance to run. Lets fix this now.

using sleep
package main

import (
    "fmt"
    "time"
)

func hello() {
    fmt.Println("Hello world")
}

func main() {
    go hello()
    time.Sleep(1 * time.Second)
    fmt.Println("Hello this is main function")
}

Output

Hello world 
Hello this is main function

Run in playground

In the above program, we have called the Sleep method of the time package which sleeps the go routine in which it is being executed.

In this case the main goroutine is put to sleep for 1 second. Now the call to go hello() has enough time to execute before the main Goroutine terminates.

This program first prints Hello world, waits for 1 second and then prints Hello this is main function.

This way of using sleep in the main Goroutine to wait for other Goroutines to finish their execution is a hack we are using to understand how Goroutines work.

Channels can be used to block the main Goroutine until all other Goroutines finish their execution. We will discuss channels in the next tutorial.

package main

import (
    "fmt"
    "time"
)

func display(str string) {
    for w := 0; w < 6; w++ {
        time.Sleep(1 * time.Second)
        fmt.Println(str)
    }
}

func main() {
    go display("Welcome")
    display("Waytoeasylearn")
}

Output

Welcome 
Waytoeasylearn 
Waytoeasylearn 
Welcome 
Welcome 
Waytoeasylearn 
Waytoeasylearn 
Welcome 
Welcome 
Waytoeasylearn 
Welcome 
Waytoeasylearn

Run in playground

Starting multiple Goroutines

Lets write one more program that starts multiple Goroutines

package main

import (
    "fmt"
    "time"
)

func numbers() {
    for i := 1; i <= 5; i++ {
        time.Sleep(300 * time.Millisecond)
        fmt.Printf("%d ", i)
    }
}

func alphabets() {
    for i := 'a'; i <= 'e'; i++ {
        time.Sleep(400 * time.Millisecond)
        fmt.Printf("%c ", i)
    }
}

func main() {
    go numbers()
    go alphabets()
    time.Sleep(3000 * time.Millisecond)
    fmt.Println("Main terminated")
}
1 a 2 b 3 4 c 5 d e main terminated

Run in playground

The above program starts two Goroutines. These two Goroutines now run concurrently. The numbers Goroutine sleeps initially for 300 milliseconds and then prints 1, then sleeps again and prints 2 and the same cycle happens till it prints 5.

Similarly the alphabets Goroutine prints alphabets from a to e and has 400 milliseconds sleep time. The main Goroutine initiates the numbers and alphabets Goroutines, sleeps for 3000 milliseconds and then terminates.

Advantages of Goroutines
  • Goroutines are cheaper than threads.
  • These are stored in the stack and the size of the stack can grow and shrink according to the requirement of the program. But in threads, the size of the stack is fixed.
  • Goroutines can communicate using the channel and these channels are specially designed to prevent race conditions when accessing shared memory using Goroutines.
  • Suppose a program has one thread, and that thread has many Goroutines associated with it. If any of Goroutine blocks the thread due to resource requirement then all the remaining Goroutines will assign to a newly created OS thread. All these details are hidden from the programmers.
Anonymous Goroutine

In Go language, you can also start Goroutine for an anonymous function or in other words, you can create an anonymous Goroutine simply by using go keyword as a prefix of that function.

package main

import (
    "fmt"
    "time"
)

func main() {
   fmt.Println("Welcome to Main function")
   // Creating Anonymous Goroutine 
   go func() {
      fmt.Println("Welcome to Waytoeasylearn")
   }()
   time.Sleep(1 * time.Second)
   fmt.Println("GoodBye to Main function")
}

Output

Welcome to Main function 
Welcome to Waytoeasylearn 
GoodBye to Main function

Run in playground

Goroutines


Scroll to top