Is the main function runs as a goroutine?

前端 未结 3 811
野的像风
野的像风 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).

    0 讨论(0)
  • 2020-12-12 00:51

    Is the main function a goroutine?

    No.

    The main function is a function.

    In contrast,

    A goroutine is a lightweight thread of execution. (source).

    So goroutines execute functions, but goroutines are not functions, and there is not a 1-to-1 relationship between goroutines and functions.

    However...

    The main() function is executed in the first (and at startup, only) goroutine, goroutine #1.

    But as soon as that function calls another function, then the main goroutine is no longer executing the main function, and is instead executing some other function.

    So it's clear that a goroutine and a function are entirely different entities.

    Do not conflate goroutines with functions!!

    Functions and goroutines are entirely different concepts. And thinking of them as the same thing will lead to countless confusion and problems.

    0 讨论(0)
  • 2020-12-12 00:52

    Yes. Main func can spawn other goroutines, but "main" itself is one groutine.

    package main
    
    import (
            "fmt"
            "runtime"
    )
    
    func main() {
            // Goroutine num includes main processing
            fmt.Println(runtime.NumGoroutine()) // 1
    
            // Spawn two goroutines
            go func() {}()
            go func() {}()
    
            // Total three goroutines run
            fmt.Println(runtime.NumGoroutine()) // 3
    }
    
    0 讨论(0)
提交回复
热议问题