Pankaj Bagwan
Pankaj Bagwan
2 min read

Categories

Tags

Go came to existance to solve problems being faced by today’s software, one of them is concurrency (ability to execute stuff in parallel while providing control and communication among them). To solve this go has provided goroutines to execute stuff in parallel.

By default, main function of package in go is run concurrently, implicitly. For expliit call we pass code block(that needs to be executed in routine) to go

package main

import "fmt"

func printer(a int){
  fmt.Println("a is: ", a)
}

func main(){
  fmt.Println("At the start")
  for i := 0; i < 10; i++ {
    fmt.Println("Sending to routine: ", i)
    go printer(i)
  }
  var get string
  fmt.Scanln(&get)
  fmt.Println("At the end!")
}

//At the start
//Sending to routine:  0
//Sending to routine:  1
//Sending to routine:  2
//Sending to routine:  3
//Sending to routine:  4
//Sending to routine:  5
//Sending to routine:  6
//Sending to routine:  7
//Sending to routine:  8
//Sending to routine:  9
//a is:  0
//a is:  1
//a is:  2
//a is:  3
//a is:  4
//a is:  5
//a is:  6
//a is:  7
//a is:  8
//a is:  9
//
//At the end!

Notice fmt.Scanln(&get); this actually makes our main program to wait for inputs, otherwise it will exit before go routine actualy can print. A problem with this code is that, it looks synchronous, in order. To actually see that if goroutine are asynchronous, we need to make goroutine sleep for random time. Lets rewrite this as:

package main

import(
  "fmt"
  "time"
  "math/rand"
)

func printer(a int){
  time.Sleep(time.Millisecond * time.Duration(rand.Intn(100)))
  fmt.Println("a is: ", a)
}

func main(){
  fmt.Println("At the start")
  for i := 0; i < 10; i++ {
    fmt.Println("Sending to routine: ", i)
    go printer(i)
  }
  var get string
  fmt.Scanln(&get)
  fmt.Println("At the end!")
}

// time.Duration(rand.Intn(100)) will make goroutine sleep for varying time
//At the start
//Sending to routine:  0
//Sending to routine:  1
//Sending to routine:  2
//Sending to routine:  3
//Sending to routine:  4
//Sending to routine:  5
//Sending to routine:  6
//Sending to routine:  7
//Sending to routine:  8
//Sending to routine:  9
//a is:  9
//a is:  5
//a is:  6
//a is:  7
//a is:  2
//a is:  8
//a is:  3
//a is:  0
//a is:  4
//a is:  1
//
//At the end!

Look at this, now it is random. This illustrates that go routine are independent to each other and runs separately.

Now what we showcased so far is called parallelism, we still need to make them communicate to each other and channels comes to our rescue. Channels provide a mechanism of communication and synchronisation among goroutines. Lets look at example.

package main

import (
  "fmt"
  "time"
)

func sender(ch chan int) {
  for i := 0; ; i++ {
    ch <- i
  }
}
func receiver(ch chan int) {
  for {
    message := <- ch
    fmt.Println("received: ", message)
    time.Sleep(time.Millisecond * 100)
  }
}
func main() {
    var ch chan int = make(chan int)

    go sender(ch)
    go receiver(ch)

    var input string
    fmt.Scanln(&input)
}

That’s interesting. This is just a simple example of channels capabilities, there is much more.


About The Author

I am Pankaj Baagwan, a System Design Architect. A Computer Scientist by heart, process enthusiast, and open source author/contributor/writer. Advocates Karma. Love working with cutting edge, fascinating, open source technologies.

  • To consult Pankaj Bagwan on System Design, Cyber Security and Application Development, SEO and SMO, please reach out at me[at]bagwanpankaj[dot]com

  • For promotion/advertisement of your services and products on this blog, please reach out at me[at]bagwanpankaj[dot]com

Stay tuned <3. Signing off for RAAM