Is the main function runs as a goroutine?

前端 未结 3 819
野的像风
野的像风 2020-12-12 00:28

Is the main() function runs as a goroutine? For example, I\'ve seen a crash stack trace like the below, which makes me ask:

goroutine 1 [running         


        
3条回答
  •  抹茶落季
    2020-12-12 00:50

    Yes, the main function runs as a goroutine (the main one).

    According to https://tour.golang.org/concurrency/1

    A goroutine is a lightweight thread managed by the Go runtime. go f(x, y, z) starts a new goroutine running f(x, y, z) The evaluation of f, x, y, and z happens in the current goroutine and the execution of f happens in the new goroutine.
    Goroutines run in the same address space, so access to shared memory must be synchronized. The sync package provides useful primitives, although you won't need them much in Go as there are other primitives.

    So according to this official document the main is the current goroutine.
    To be precise (literally) we could address the main as the current goroutine, so simply speaking it is a goroutine. (Note: Literally speaking the main() is a function which could run as a goroutine.)


    Now let's count the number of goroutines using runtime.NumGoroutine():

    As an example let's run 3 goroutines. Try it online:

    package main
    
    import (
        "fmt"
        "runtime"
        "time"
    )
    
    func main() {
        fmt.Println(runtime.NumGoroutine()) // 3
        time.Sleep(100 * time.Millisecond)
    }
    func init() {
        go main()
        go main()
    }
    
    

    Here the current goroutine runs the new goroutine, so here we have more than one goroutine, which executes main() again. Try it online:

    package main
    
    import (
        "fmt"
        "runtime"
        "sync/atomic"
        "time"
    )
    
    func main() {
        fmt.Println(runtime.NumGoroutine()) // 1 2 3 4
        if atomic.LoadInt32(&i) <= 0 {
            return
        }
        atomic.AddInt32(&i, -1)
        go main()
        time.Sleep(100 * time.Millisecond)
    }
    
    var i int32 = 3
    

    Output:

    1
    2
    3
    4
    

    Here we have one main goroutine plus 3 user called main goroutines, so total number of goroutines are 4 here.


    Let's calculate factorial using main() (one goroutine - no synchronization needed). Try it online:

    package main
    
    import "fmt"
    
    func main() {
        if f <= 0 {
            fmt.Println(acc)
            return
        }
        acc *= f
        f--
        main()
    }
    
    var f = 5
    var acc = 1
    
    

    Output:

    120
    

    Note: The codes above are just for clearly showing my viewpoints and is not good for production use (Using global variables should not be the first choice).

提交回复
热议问题