I recently started learning Go and there is a case that i have been written that i cannot understand why does he get two different behaviors based on a change made in a single line that just prints [line 13],
In the first run i run the program with [line 13] and then in the main routine when i print the length of the channel at [line 21] that print 0 and in the next line thats just come after that its print 2 (I'm talking about the first print that the main routine made).
In the second run i removed [line 13] and then in both prints in the first time that print thats the length of the channel is 2.
in the picture you can see in the console the two diffrents prints that i dont understand why they are different [just because add/remove line 13].
// Go behavior that I do not understand /:
package main
import "fmt"
func main() {
mychnl := make(chan string, 2)
go func(input chan string) {
input <- "Inp1"
// If we remove this line the length of the chan in the print will be equal in both prints
fmt.Println("Tell me why D:")
input <- "Inp2"
input <- "Inp3"
input <- "Inp4"
close(input)
}(mychnl)
for res := range mychnl {
fmt.Printf("Length of the channel is: %v The received value is: %s length need to be == ", len(mychnl), res)
fmt.Println(len(mychnl))
}
}
/*
Output ->
Line 13 = fmt.Println("Tell me why D:")
First run with line 13:
Tell me why D:
Length of the channel is: 0 The received value is: Inp1 length need to be == 2
Length of the channel is: 2 The received value is: Inp2 length need to be == 2
Length of the channel is: 1 The received value is: Inp3 length need to be == 1
Length of the channel is: 0 The received value is: Inp4 length need to be == 0
Second run without line 13:
Length of the channel is: 2 The received value is: Inp1 length need to be == 2
Length of the channel is: 2 The received value is: Inp2 length need to be == 2
Length of the channel is: 1 The received value is: Inp3 length need to be == 1
Length of the channel is: 0 The received value is: Inp4 length need to be == 0
*/
CodePudding user response:
The behavior you're seeing is due to a race condition. Generally, you can't be sure when the main goroutine will print the length of the channel compared to when the other goroutine will write to it.
By adding the print statement, you cause additional I/O (to stdout), which in turn often means that goroutines yield execution and are rescheduled. So it's not surprising that the Print
changes how fast your goroutine writes to the channel.
When designing programs with channels, keep in mind that you must not care too much when concurrent operations on the channel happen . Will one, two, or zerothings be on the channel when you read from it? There's no way to know, because the channel is buffered and the two goroutines are likely to run concurrently on the multiple cores of modern computers. len()
of a buffered channel is likely to lead to a variety of possible values, and you shouldn't rely on it for algorithmic correctness.