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
-
creating Goroutines
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
- Define Critical Sections using Mutex
- Fix Race Condition using Atomic Functions
- Channel can be used to fetch return value from a goroutine. Channel provides synchronization and communication between goroutines.