Tuesday, April 30, 2024

Mastering Go: Part 4 - Concurrency in Go

Concurrency in Go

Concurrency is the capability to execute multiple tasks simultaneously. Due to the demand for efficient and high-speed processing with multicore processors, 'Go' was developed to facilitate concurrent programming. By leveraging Go subroutines and channels, we can write concurrent programs in Go.

Goroutines

A Goroutine is a thread managed by the Go runtime. When a function is invoked with the 'go' keyword prefix, a new Goroutine will be initiated.

Channels

A channel serves as the communication medium between two Goroutines. It's a type that facilitates the transmission and reception of values. By utilizing channels, Goroutines can synchronize without the need for explicit locking mechanisms. Since Goroutines do not return values directly, channels are employed to retrieve results from Goroutine executions.

ch := make(chan string)// Create channel
ch <- stringData // send data to the channel
stringVariable := <-ch // receive data from channel 

Buffered Channel

We can specify the buffer length to initialize a buffered channel.

ch := make(chan string, 2)

In the buffered channel above, we cannot have more than 2 values.

Close channel

The goroutine can close the channel if there are no more values to pass to the process that invoked the goroutine. Similarly, the goroutine invoker can check whether the channel has been closed or not after receiving the final value.

stringVariable, channelStatus := <-ch

Here, the variable channelStatus will contain the status of the channel. If the channel is closed, channelStatus will be false.

Select

The select statement lets a goroutine wait on multiple communication operations.

Mutex

This assures only one goroutine can access a variable at a time to avoid conflict and will be used by locking and unlocking the block of code.

Exercise

Exercise- Continue the exercise from the last part of this learning series
Mastering Go: Part 3 - Programming paradigm(OOP and procedural)
 
Step 1: Modify the signature of the formatString function to add one more parameter of type chan to receive the channel type variable.

Step 2: Modify the main method and create a new variable of chan type.

Step 3: Call the formatString function for PersonName and Address struct types prefixed with the 'go' keyword.

Update the main method with the following code, and observe the modifications made to the signature of the function formatString and how it is called from the main method:

package main

import (
"fmt"
dateformater "learngo/date_formater" // import data formater package
stringformater "learngo/string_formater" // import string formater package
)

func main() {

fmt.Println("Crete new date instance using a constructor!")
dateConstructor := dateformater.NewDate("2021", "07", "01")
fmt.Println(dateConstructor.Format())

// Create a channel to communicate and receive data between goroutines
ch := make(chan string)

fmt.Println("Use name format package to format name!")
// Create the instance of PersonName struct
personName := &stringformater.PersonName{FirstName: "Sharad", LastName: "Subedi"}
go formatString(personName, ch)
formatedName := <-ch // receive formatted data from channel
fmt.Println(formatedName)

fmt.Println("Use name format package to format billing address!")
//create the instance of the Address struct
address := &stringformater.Address{StreetNumber: "123", StreetName: "Main St", City: "San Francisco", State: "CA", Zip: "94101"}
go formatString(address, ch)
formatedAddress, channelStatus := <-ch // receive formatted data from channel with channel status
fmt.Println(formatedAddress)

// Check the status of the channel
if channelStatus {
fmt.Println("Channel Ch is not closed! The last value is %s", formatedAddress)
} else {
fmt.Println("Channel Ch is closed! The last value received from channel is %s", formatedAddress)
}

}

// function to format the strings. Takes the interface type as input.
// Example to implement polymorphism using interface
func formatString(formater stringformater.Formater, ch chan string) {
ch <- formater.Format()
}


Reference

https://go.dev/tour/concurrency/2

1 comment:

  1. Nice and Straightforward overview of concurrent coding in Go.

    ReplyDelete

Mastering Go: Part 14 - Messaging with Apache Kafka(Go Implementation)

In this post, we will explore how to implement Apache Kafka messaging in Golang. Several packages are available, and the best choice depends...