Reputation: 29
I am a newbie in Golang and I am trying to understand the goroutines. Here is the piece of code which I got from https://www.golangprograms.com/goroutines.html.
package main
import (
"fmt"
"runtime"
"sync"
"sync/atomic"
)
var (
counter int32 // counter is a variable incremented by all goroutines.
wg sync.WaitGroup // wg is used to wait for the program to finish.
)
func main() {
wg.Add(3) // Add a count of two, one for each goroutine.
go increment("Python")
go increment("Java")
go increment("Golang")
wg.Wait() // Wait for the goroutines to finish.
fmt.Println("Counter:", counter)
}
func increment(name string) {
defer wg.Done() // Schedule the call to Done to tell main we are done.
for range name {
fmt.Println("name:", name)
fmt.Println("Counter in range:", counter)
atomic.AddInt32(&counter, 1)
runtime.Gosched() // Yield the thread and be placed back in queue.
}
}
Output:
name: Golang
Counter in range: 0
name: Java
Counter in range: 1
name: Golang
Counter in range: 2
name: Golang
Counter in range: 3
name: Java
Counter in range: 4
name: Golang
Counter in range: 5
name: Python
Counter in range: 6
name: Java
Counter in range: 7
name: Golang
Counter in range: 8
name: Java
Counter in range: 9
name: Golang
Counter in range: 10
name: Python
Counter in range: 11
name: Python
Counter in range: 12
name: Python
Counter in range: 13
name: Python
Counter in range: 14
name: Python
Counter in range: 15
Counter: 16
I am unable to understand that why the output is 16. Even we added only 3 goroutines. Shouldn't it be 3?
Can anyone please explain me?
Thanks.
Upvotes: 0
Views: 657
Reputation: 747
You are range over the given input string, trange treat it as an array and iterates over it. See this example
package main
import (
"fmt"
)
func main() {
increment("test")
increment("test_dev")
increment("test_deploy")
}
func increment(name string) {
for i, value := range name {
fmt.Printf("name: %s index: %d, char: %c\n", name, i, value)
}
}
Upvotes: 0
Reputation: 417652
I am unable to understand that why the output is 16. Even we added only 3 goroutines. Shouldn't it be 3?
Why should it be 3? It should be as many times atomic.AddInt32(&counter, 1)
is called.
How many times is that? You launch 3 goroutines, and each has a loop. Incrementing is done inside the loops.
The loops:
for range name {}
The for range
over a string
iterates over the runes of the string
. The names in your case are Golang
, Java
and Python
. So the loop bodies will be executed as many times as many runes these strings have: 6 for Golang
, 4 for Java
and 6 for Python
, that adds up to 16.
Upvotes: 3