为什么我需要睡两次才能看到goroutine?

I've written this little program with go. About go keyword, I just know that when I call a function in this manner, is executed simultaenously. What I've tried to execute this code without time.Sleep(), but no output is generated. I need to add time.Sleep(1000) twice. One time.Sleep statement is not enough. Why?

package main

import (
    "fmt"
    "time"
)

func doSomething(integer int) {
    fmt.Println(integer)
}

func main() {
    i := 1

    for i <= 10 {
        go doSomething(i)
        i++
    }

    time.Sleep(1000)
    time.Sleep(1000)
}

That's because when you call a function with go (ie as a goroutine) it is run in the background and execution continues. In this case, you have nothing for the program to do after invoking the goroutine so it just completes and you see no output. Why do you need two? Well you don't, it's just the 1 second sleep wasn't long enough, if you had time.Sleep(2000) you'd probably get the same result (though it's not guaranteed). Generally when using a goroutine, you need some kind of blocking statement some where. The simplest way to do this, imo, is to pass a channel to the goroutine and then receive from it.

This isn't the most useful example due to the structuring of your code, but here's a modified version of your program that will block until the first goroutine completes. Since you're actually invoking 10 goroutines, you would need a bit more robust logic to block until of them complete but a more reasonable solution would be to put the loop in the gouroutine, rather than invoking 10 goroutines. https://play.golang.org/p/66g9u8Bhjj

Also, check out this more realistic example in the go tour; https://tour.golang.org/concurrency/2

try this:

package main

import (
    "fmt"
    "runtime"
    "time"
)

func doSomething(integer int) {
    fmt.Println(integer)
}

func main() {
    i := 1

    for i <= 10 {
        go doSomething(i)
        i++
    }
    runtime.Gosched()
    time.Sleep(10 * time.Millisecond)
}

It will runs differently.

Do you know how much time it takes to finish this (your) code:
(Consider CPU Loaded 100% with other process with higher priority.)

func doSomething(integer int) {
    fmt.Println(integer)
}
for i <= 10 {
    go doSomething(i)
    i++
}

Simple answer: no.
It depends to many unknown factors on each system:
1- CPU speed and number of CPU cores and CPU caches...
2- RAM speed and bus speed and bus matrix (is it concurrent?)
2- OS scheduler and OS Load and priority
3- Golang scheduler
4- CPU Load
...

What I mean is: In concurrent systems and concurrent programming it is not good idea to rely on simple code (or assembly) instruction timing.

Yes it is good to know Golang scheduler and how it works, but Even you know how Golang scheduler behaves, do you know what OS doing now?

Only in real-time OS it is estimated to some known time in the ranges like milliseconds or so.

even sometimes it is better to limit concurrency:
this is one way to limit the concurrency:

//using chan to limit the concurrency
package main

import (
    "os/exec"
    "runtime"
    "sync"
)

func main() {
    numberOfJobs := 10
    c := make(chan *exec.Cmd, numberOfJobs)
    for i := 0; i < numberOfJobs; i++ {
        c <- exec.Command("notepad")
    }
    close(c)

    nCPU := runtime.NumCPU()
    var wg sync.WaitGroup
    for i := 0; i < nCPU; i++ {
        wg.Add(1)
        go func() {
            for cmd := range c {
                cmd.Run()
            }
            wg.Done()
        }()
    }

    wg.Wait()
}

this is another way to limit the concurrency:

//using chan to limit the concurrency
package main

import (
    "os/exec"
    "runtime"
    "sync"
)

func main() {
    n := runtime.NumCPU()
    dummy := make(chan bool, n)
    numberOfJobs := 10
    var wg sync.WaitGroup
    for i := 0; i < numberOfJobs; i++ {
        cmd := exec.Command("notepad")
        dummy <- true // wait here if no CPU available
        wg.Add(1)
        go func(cmd *exec.Cmd) {
            //defer func() { <-dummy }()
            cmd.Run()
            wg.Done()
            <-dummy
        }(cmd)
    }
    close(dummy)

    wg.Wait()
}

I hope this helps.