Goroutines in Go Language
In Go language, Goroutine is a lightweight
execution thread. It is a
function that runs concurrency alongside other running code.
Note: - concurrent execution may or may not parallel. In Go, every program has at least one goroutine: the main goroutine. A goroutine is started with the go keywords.
To run a function as a goroutine, call that function prefixed with the go statement
by using the go keyword as a prefixing to the function or method call as shown below:
Syntax:
func name(){
// statements
}
// using the go keyword as the
// prefix of your function call
go name()
- Program to illustrate the creation of Goroutines.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
)
func responseSize(url string) {
fmt.Println("Step1: ", url)
response, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
fmt.Println("Step2: ", url)
defer response.Body.Close()
fmt.Println("Step3: ", url)
body, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println("Step4: ", len(body))
}
func main() {
go responseSize("https://www.prwatech.com/")
go responseSize("https://www.prwatech.com/pages/project")
go responseSize("https://www.prwatech.com/pages/jobs")
time.Sleep(10 * time.Second)
}
Output :
PS C:\GO_Language\Goroutines> go run g.go
Step1: https://www.prwatech.com/pages/jobs
Step1: https://www.prwatech.com/
Step1: https://www.prwatech.com/pages/project
Step2: https://www.prwatech.com/pages/project
Step3: https://www.prwatech.com/pages/project
Step4: 1098718
Step2: https://www.prwatech.com/pages/jobs
Step3: https://www.prwatech.com/pages/jobs
Step4: 193698
Step2: https://www.prwatech.com/
Step3: https://www.prwatech.com/
Step4: 98907
- Waiting for Goroutines to Finish Execution
-
- ADD: - used to add a counter to the Wait Group.
- DONE: - The Done method of Wait Group is scheduled using a defer statement to decrement the Wait Group counter.
- WAIT: - The Wait method of the Wait Group type waits for the program to finish all goroutines.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"sync"
)
var wg sync.WaitGroup
func responseSize(url string) {
defer wg.Done()
fmt.Println("Step1: ", url)
response, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
fmt.Println("Step2: ", url)
defer response.Body.Close()
fmt.Println("Step3: ", url)
body, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println("Step4: ", len(body))
}
func main() {
wg.Add(3)
fmt.Println("Start Goroutines")
go responseSize("https://www.prwatech.com/")
go responseSize("https://www.prwatech.com/pages/project")
go responseSize("https://www.prwatech.com/pages/jobs")
wg.Wait()
fmt.Println("Terminating Program")
}
Output :
PS C:\GO_Language\Goroutines> go run g2.go
Start Goroutines
Step1: https://www.prwatech.com/pages/jobs
Step1: https://www.prwatech.com/
Step1: https://www.prwatech.com/pages/project
Step2: https://www.prwatech.com/pages/project
Step3: https://www.prwatech.com/pages/project
Step4: 1098718
Step2: https://www.prwatech.com/pages/jobs
Step3: https://www.prwatech.com/pages/jobs
Step4: 193698
Step2: https://www.prwatech.com/
Step3: https://www.prwatech.com/
Step4: 98907
Terminating Program
-
Fetch Values from Goroutines in Go lang.
-
- Channel can be used to fetch return value from a goroutine. Channel provides synchronization and communication between goroutines.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"sync"
)
var WG sync.WaitGroup
func responseSize(url string, num chan int) {
defer WG.Done()
response, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
num <- len(body)
}
func main() {
num := make(chan int)
WG.Add(1)
go responseSize("https://prwatech.in/", num)
fmt.Println(<-num)
WG.Wait()
close(num)
}
Output :
PS C:\GO_Language\Goroutines> go run g3.go
114307
- Play and Pause Execution of Goroutine in Go Lang.
- A channel handles this communication by acting as a conduit between goroutines.
package main
import (
"fmt"
"sync"
"time"
)
var x int
func work() {
time.Sleep(100 * time.Millisecond)
x++
fmt.Println(x)
}
func routine(command <-chan string, WG *sync.WaitGroup) {
defer WG.Done()
status := "PLAY"
for {
select {
case cmd := <-command:
fmt.Println(cmd)
switch cmd {
case "STOP":
return
case "PAUSE":
status = "PAUSE"
default:
status = "PLAY"
}
default:
if status == "PLAY" {
work()
}
}
}
}
func main() {
var WG sync.WaitGroup
WG.Add(1)
commandS := make(chan string)
go routine(commandS, &WG)
time.Sleep(1 * time.Second)
commandS <- "PAUSE"
time.Sleep(1 * time.Second)
commandS <- "PLAY"
time.Sleep(1 * time.Second)
commandS <- "STOP"
WG.Wait()
}
Output :
PS C:\GO_Language\Goroutines> go run g4.go
1
2
3
4
5
6
7
8
9
PAUSE
PLAY
10
11
12
13
14
15
16
17
18
19
STOP
- Fix Race Condition using Atomic Functions
package main
import (
"fmt"
"runtime"
"sync"
"sync/atomic"
)
var (
counter int32
wg sync.WaitGroup
)
func main() {
wg.Add(3)
go increment("Python")
go increment("Java")
go increment("Golang")
wg.Wait()
fmt.Println("Counter:", counter)
}
func increment(name string) {
defer wg.Done()
for range name {
atomic.AddInt32(&counter, 1)
runtime.Gosched()
}
}
Output :
PS C:\GO_Language\Goroutines> go run g5.go
Counter: 16
- Define Critical Sections using Mutex
package main
import (
"fmt"
"sync"
)
var (
counter int32
wg sync.WaitGroup
mutex sync.Mutex
)
func main() {
wg.Add(3)
go increment("Python")
go increment("Go Programming Language")
go increment("Java")
wg.Wait()
fmt.Println("Counter:", counter)
}
func increment(lang string) {
defer wg.Done()
for i := 0; i < 3; i++ {
mutex.Lock()
{
fmt.Println(lang)
counter++
}
mutex.Unlock()
}
}
Output :
PS C:\GO_Language\Goroutines> go run g6.go
Java
Java
Java
Python
Python
Python
Go Programming Language
Go Programming Language
Go Programming Language
Counter: 9
Goroutines in Go Language