I agree with @Lauren Sanchez. This difference is because the goroutine in the first example captures a new variable memory for each ittr. However, in the second example, all goroutines refer to the same memory, hence printing the same value (this will be different if you run this test multiple times, depending on when the goroutine is executed).
I always want to be very safe when adding a goroutine in a loop, so I always pass the variable to the goroutine to make sure I do not mess it up.
for instance I would have modified the code as below:
var i int
for i = 0; i < 10; i++ {
go func(num int) {
time.Sleep(time.Second)
fmt.Printf("%d %d \n", num, i)
}(i)
}
time.Sleep(2 * time.Second)