time.Sleep resulting undesired behavior [duplicate] - go

This question already has an answer here:
goroutines order of execution
(1 answer)
Closed 2 years ago.
import "fmt"
import "time"
func main() {
array := []int{1, 2, 3}
for _, num := range array {
go func() {
fmt.Println(fucknum)
}(fucknum)
time.Sleep(time.Nanosecond)
}
time.Sleep(time.Second)
}
Since there is a time.Sleep within the for-loop, I was expecting the output to be 1 2 3 because of the yielding of execution at each time.Sleep.
However, the output of this piece of code outputs 2 1 3. And after I changed Nanosecond to Microsecond, it turns to be 1 2 3.
For comparison, I also tested python3's asyncio version in which I assume asyncio.call_soon is equivalent to Go's non-IO coroutine.
import asyncio
loop = asyncio.get_event_loop()
async def test():
for i in range(1, 4):
# replace call_soon with asyncio.sleep(0) does not change the result
loop.call_soon(lambda : print(i))
await asyncio.sleep(0)
loop.run_until_complete(test())
And the outputs are always 1 2 3(This output is the same as what I expected as I know that internally, functions scheduled by call_soon is simply added into a FIFO queue)
How to explain the behavior of the Go version?

Because each of the generated goroutines are accessing the same variable defined outside of their scope they are not allocating a new memory address, but are referencing the same address. The for loop in your example actually references the same variable multiple times. By introducing a local scope in the goroutine definition, each time a new goroutine is spawned it will allocate a new variable on each iteration.
To solve the problem you need to pass the index as a parameter for your closure function.
This should fix your problem.
func main() {
array := []int{1, 2, 3}
for _, num := range array {
go func(num int) {
fmt.Println(num)
}(num)
time.Sleep(time.Nanosecond)
}
time.Sleep(time.Second)
}

Related

fmt.Println is not executing in order when used without sleep

I'm trying to understand, why my code doesn't behave as I expect it. The problem is that I would expect, that my code would behave like that:
Define channel
Run goroutine and start looping
Put value into channel, print "finished"
Starting second iteration, blocking call(there is already value in the channel), move to main goroutine
Printing 1, trying to run second iteration, blocking call for main goroutine, coming back to second goroutine
Cycle repeats
It works like that, but only with time.Sleep, but for some reason when commenting out time.Sleep it behaves totally different. What's even more interesting that sometimes for really small values of time like Nanos etc this code returns even more different results. Could someone explain me, why it works like that? My guess is that maybe Println is too slow on display, but it sounds weird to me..
Thanks
** As expected: **
finished
1
finished
2
finished
3
finished
6
finished
4
finished
8
finished all
** Not expected **
finished
1
2
finished
finished
3
finished
6
4
finished
finished
8
finished all
func main() {
var c chan int = make(chan int)
go sendingThrowingResults(c)
for val := range c {
fmt.Println(val)
}
fmt.Println("finished all")
}
func sendingThrowingResults(c chan int) {
var results []int = []int{1, 2, 3, 6, 4, 8}
for _, val := range results {
//time.Sleep(100 * time.Millisecond)
c <- val
fmt.Println("finished")
}
defer close(c)
}
A channel operation needs both sides to participate. A write only happens when a reader is ready. Once that happens, there is no guarantee on which goroutine will run first.
Thus, once the channel write happens, one of the two printlns will work, in some random order.

how to understand scope in go closure

Does anybody know why the case1 output the same result, but the case2 output the sequential result?
I know the reason why case1 output the same value is that the closure of each function in functions slice access to the same scope.
But why after adding i:=i in each loop can case2 output the sequential result?
Does after redefining i in eachloop, a new scope is generated?
like let in javascript?
case1
func main() {
funcs := []func() {}
for i:=0;i<10;i++{
funcs = append(funcs, func() {
fmt.Println(i)
})
}
for i:=0;i<10;i++{
funcs[i]()
}
}
output
10
10
10
10
10
10
10
10
10
10
case2
func main() {
funcs := []func() {}
for i:=0;i<10;i++{
i := i
funcs = append(funcs, func() {
fmt.Println(i)
})
}
for i:=0;i<10;i++{
funcs[i]()
}
}
output
0
1
2
3
4
5
6
7
8
9
This isn't really a scope issue but rather an issue with how the compiler decides if your variable i is captured by reference or by value. This is not always obvious. For loops in go reuse the iteration variable in this case the i. In case1 the variable i is captured as a reference as the compiler sees it as being changed after the capture has taken place. In case2 the inner variable i is created before the capture, captured and released thus the compiler sees it as unchanging and captures it by value. The result is when the functions are run in case1 the results are all the final value as that is what the variable i ended up as and each function only holds a reference to that particular i. In case2 each capture was passed a "copy" of i at the time of creation thus they show the values you expect.

Never ending Ticker in Golang works only 2 times

I'm trying to make a channel with never ending ticker, but it works only 2 times.
Could you help me to understand where is the problem?
Code:
package main
import (
"fmt"
"time"
)
var mark = [2]float64{8.9876, 762.098568}
func tick(out chan <- [2]float64){
c := time.NewTicker(time.Millisecond *500)
for range c.C{
out <- mark
}
}
func main() {
fmt.Println("Start")
md := make(chan [2]float64)
go tick(md)
for range <-md{
fmt.Println(<-md)
}
}
Output:
Start
[8.9876 762.098568]
[8.9876 762.098568]
Example: https://play.golang.org/p/P2FaUwbW-3
This:
for range <-md{
is not the same as:
for range md{
The latter ranges over the channel (what you want), while the former ranges over the value received from the channel when the loop starts, which happens to be a two-element array, hence the two executions. You're also ignoring the value received from the channel in the for statement, and reading from it again in the loop body, ignoring every other message on the channel (though this makes no difference in the example, since every value is identical, it would make a significant difference in practice). What you really want is:
for foo := range md{
fmt.Println(foo)
}
Here's a working version of your playground example, slightly modified to avoid "program took too long" errors because in its current form it never stops: https://play.golang.org/p/RSUJFvluU5

golang: Why the following code does NOT panic with "slice index out of range" error [duplicate]

This question already has answers here:
Appending one element to nil slice increases capacity by two
(4 answers)
Closed 6 years ago.
package main
import "fmt"
type Point struct {
X int
Y int
}
type Points struct {
P []Point
}
func main() {
data := Points{}
for i := 0; i < 10; i++ {
data.P = append(data.P, Point{
X: i,
Y: i*2,
})
}
fmt.Printf("%+v\n", data.P[5:11]);
}
While the above program is run, it printed out:
[{X:5 Y:10} {X:6 Y:12} {X:7 Y:14} {X:8 Y:16} {X:9 Y:18} {X:0 Y:0}]
Why there are {X:0, Y:0} which seems to be automatically generated as the slice's length is 10 but I try to get 5:11?
I found the problem in my code and test with "raw" slice such as:
package main
import "fmt"
func main() {
v := []int{0,1,2,3,4,5,6,7,8,9}
fmt.Printf("%v\n", v[5:11])
}
This simple program generates errors (as expected):
panic: runtime error: slice bounds out of range
goroutine 1 [running]:
panic(0x47a8e0, 0xc42000a130)
/usr/local/go/src/runtime/panic.go:500 +0x1a1
main.main()
/home/fxr/go/src/cmhwc/test2.go:7 +0x53
exit status 2
Why the first program does not panic?
Because when you use append() to add elements to a slice which has no more room for adding the new elements it creates a new one doubling its capacity copying the old elements as well as the new you're asking to add and returning a reference to that. Further down when you use slice syntax to ask for elements past the apparent end of the slice the length is actually applied to the underlying array created & returned by append.
As #JimB suggested in the comments, you can add a statement to print the capacity at every step in the append loop to see this happening:
fmt.Println(cap(data.P))
Should generate something like:
2
2
4
4
8
8
8
8
16
16

How golang's "defer" capture closure's parameter?

Here is my code (run):
package main
import "fmt"
func main() {
var whatever [5]struct{}
for i := range whatever {
fmt.Println(i)
} // part 1
for i := range whatever {
defer func() { fmt.Println(i) }()
} // part 2
for i := range whatever {
defer func(n int) { fmt.Println(n) }(i)
} // part 3
}
Output:
0
1
2
3
4
4
3
2
1
0
4
4
4
4
4
Question: What's the difference between part 2 & part 3? Why part 2 output "44444" instead of "43210"?
The 'part 2' closure captures the variable 'i'. When the code in the closure (later) executes, the variable 'i' has the value which it had in the last iteration of the range statement, ie. '4'. Hence the
4 4 4 4 4
part of the output.
The 'part 3' doesn't capture any outer variables in its closure. As the specs say:
Each time the "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function is not invoked.
So each of the defered function calls has a different value of the 'n' parameter. It is the value of the 'i' variable in the moment the defer statement was executed. Hence the
4 3 2 1 0
part of the output because:
... deferred calls are executed in LIFO order immediately before the surrounding function returns ...
The key point to note is that the 'f()' in 'defer f()' is not executed when the defer statement executes
but
the expression 'e' in 'defer f(e)' is evaluated when the defer statement executes.
I would like to address another example in order to improve the understanding of defer mechanish, run this snippet as it is first, then switch order of the statements marked as (A) and (B), and see the result to yourself.
package main
import (
"fmt"
)
type Component struct {
val int
}
func (c Component) method() {
fmt.Println(c.val)
}
func main() {
c := Component{}
defer c.method() // statement (A)
c.val = 2 // statement (B)
}
I keep wonderng what are the correct keywords or concepts to apply here. It looks like that the expression c.method is evaluated, thus returning a function binded to the actual state of the component "c" (like taking an snapshot of the component's internal state).
I guess the answer involves not only defer mechanish also how funtions with value or pointer receiver works. Do note that it also happens that if you change the func named method to be a pointer receiver the defer prints c.val as 2, not as 0.

Resources