Thursday, 9 May 2019

Go Language: Goroutines


Goroutine is a lightweight thread maintained by GO runtime.

How can you convert a function to goroutine?
You can convert a function to Goroutine by prefixing it with the keyword ‘go’ while calling.

Example
go printUpperAlphabets()

In the above example, printUpperAlphabets() method is executed as goroutine, that means it will execute parallelly.

Let’s see it with an example.

App.go
package main

import (
    "fmt"
)

func main() {
    printUpperAlphabets()
    printLowerAlphabets()
}

func printUpperAlphabets() {
    for alphabet := byte('A'); alphabet <= byte('Z'); alphabet++ {
        fmt.Print(string(alphabet), " ")
    }

    fmt.Println()
}

func printLowerAlphabets() {
    for alphabet := byte('a'); alphabet <= byte('z'); alphabet++ {
        fmt.Print(string(alphabet), " ")
    }

    fmt.Println()
}

As you see main method, I am calling two functions 'printUpperAlphabets' followed by 'printLowerAlphabets'. When I ran App.go application, I can see uppercase alphabets followed by lowercase alphabets printed to the console.


App.go
package main

import (
    "fmt"
)

func main() {
    printUpperAlphabets()
    printLowerAlphabets()
}

func printUpperAlphabets() {
    for alphabet := byte('A'); alphabet <= byte('Z'); alphabet++ {
        fmt.Print(string(alphabet), " ")
    }

    fmt.Println()
}

func printLowerAlphabets() {
    for alphabet := byte('a'); alphabet <= byte('z'); alphabet++ {
        fmt.Print(string(alphabet), " ")
    }

    fmt.Println()
}

Output
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z

Let’s convert the functions printUpperAlphabets, printLowerAlphabets as goroutines and re run App.go

Prefix method calls with go to run them as goroutines.

go printUpperAlphabets()
go printLowerAlphabets()


App.go
package main

import (
    "fmt"
)

func main() {
    go printUpperAlphabets()
    go printLowerAlphabets()
}

func printUpperAlphabets() {
    for alphabet := byte('A'); alphabet <= byte('Z'); alphabet++ {
        fmt.Print(string(alphabet), " ")
    }

    fmt.Println()
}

func printLowerAlphabets() {
    for alphabet := byte('a'); alphabet <= byte('z'); alphabet++ {
        fmt.Print(string(alphabet), " ")
    }

    fmt.Println()
}
ab

When you ran App.go, you will not see anything. It is because, once the main function finishes its execution, it terminates the application. Since goroutines run parallelly, we need to give some time to the main() function to terminate.

Update App.go by adding below statement at the end of main function.
time.Sleep(2 * time.Second)

Sleep method makes sure that the main() pauses for 2 seconds.


App.go
package main

import (
    "fmt"
    "time"
)

func main() {
    go printUpperAlphabets()
    go printLowerAlphabets()

    time.Sleep(2 * time.Second)
}

func printUpperAlphabets() {
    for alphabet := byte('A'); alphabet <= byte('Z'); alphabet++ {
        fmt.Print(string(alphabet), " ")
    }

    fmt.Println()
}

func printLowerAlphabets() {
    for alphabet := byte('a'); alphabet <= byte('z'); alphabet++ {
        fmt.Print(string(alphabet), " ")
    }

    fmt.Println()
}

abc
Run App.go for 3 or 4 times, you can see different results every time.

Run 1
a b c d e f g h i A B C D E F G H I J K L M N O P Q R S T U V W X Y j k l m n o p q r s t u v w Z
x y z

Run 2
A a b c d e f g h i j k l m B C D E F G H I J K L M N O P Q n o p q R S T U V W X Y Z
r s t u v w x y z

Run 3
a b c d e f A g h i j k l m n o p B C D q r s t u v w x y z
E F G H I J K L M N O P Q R S T U V W X Y Z

Since goroutines run parallelly, you are seeing different results every time.

As I said, you can make any function as goroutine by prefixing it with go keyword, you can run ‘fmt.Print’ also as a goroutine.

func printUpperAlphabets() {
    for alphabet := byte('A'); alphabet <= byte('Z'); alphabet++ {
        go fmt.Print(string(alphabet), " ")
    }

    fmt.Println()
}

How to use multi processors?
By default all the Go applications run on single processor, if you want to utilize all the processors, you can do it by using ‘runtime’ package.

runtime.GOMAXPROCS(8)
Above statement sets the maximum number of CPUs to 8, that can be executing simultaneously


App.go
package main

import (
	"fmt"
	"runtime"
	"time"
)

func main() {
	runtime.GOMAXPROCS(8)

	go printUpperAlphabets()

	time.Sleep(2 * time.Second)
}

func printUpperAlphabets() {
	for alphabet := byte('A'); alphabet <= byte('Z'); alphabet++ {
		go fmt.Print(string(alphabet), " ")
	}

	fmt.Println()
}


Previous                                                 Next                                                 Home

No comments:

Post a Comment