Goroutines in Go Language

  • date 8th September, 2022 |
  • by Prwatech |
  • 0 Comments

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()

 

  1. 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.

      1. 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
              

               

Quick Support

image image