Asynchronous execution inside for loops (Golang and Nodejs)

The following code is written to highlight the challenge of asynchronous execution inside for loops using code snippets in Golang and Nodejs

In Golang

    package main

    import (
        "fmt"
        "runtime"
    )

    func main() {

        runtime.GOMAXPROCS(1)

        for i := 1; i < 3; i++ {
            for j := 1; j < 3; j++ {
                go func() {
                    fmt.Printf("%d + %d = %d\n", i, j, i+j)
                }()
            }
        }

        fmt.Scanln()
    }

Output

(Note that the program is being executed in a single thread because of this line - runtime.GOMAXPROCS(1)). The output will be different if this line is removed as the code (goroutines) can be executed over multiple threads across cores simultaneously

3 + 3 = 6
3 + 3 = 6
3 + 3 = 6
3 + 3 = 6

Understanding code execution in Golang

To get this program to output all of the combinations of i and j (order not considered)

1 + 1 = 2
1 + 2 = 3
2 + 1 = 3
2 + 2 = 4

We can pass the variables i and j to the respective functions as arguments when they are invoked as follows

go func(i int, j int) {
	fmt.Printf("%d + %d = %d\n", i, j, i+j)
}(i, j)

Output after the above modification

1 + 1 = 2
2 + 2 = 4
2 + 1 = 3
1 + 2 = 3

Understanding code execution after modification

A similar behavior is observed when executing asynchronous tasks in Nodejs.

In Nodejs

for(var i=1; i<3; i++) {
    for(var j=1; j<3; j++) {
        setTimeout(() => {
            console.log(i+" + "+j+" = "+(i+j));
        }, 0)
    }
}

Output

3 + 3 = 6
3 + 3 = 6
3 + 3 = 6
3 + 3 = 6

There are two ways to achieve the following output in Nodejs

1 + 1 = 2
2 + 2 = 4
2 + 1 = 3
1 + 2 = 3
  1. By wrapping setTimeout within a function to which the variables i and j are passed as arguments
     (function asynchronous(i, j) {
         setTimeout(() => {
             console.log(i+" + "+j+" = "+(i+j));
         }, 0)
     })(i, j)
    
  2. By using let to declare the variables i and j which creates block scoped variables
     for(let i=1; i<3; i++) {
         for(let j=1; j<3; j++) {
             setTimeout(() => {
                 console.log(i+" + "+j+" = "+(i+j));
             }, 0)
         }
     }