Manjeet Singh
Manjeet Singh

Reputation: 2398

Is the main function run a goroutine?

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

goroutine 1 [running]: main.binarySearch(0x0, 0x61, 0x43,
0xc420043e70, 0x19, 0x19, 0x10)
     /home/---/go/src/github.com/----/sumnum.go:22 +0x80 main.main()
     /home/---/go/src/github.com/---/sumnum.go:13 +0xc1 exit status 2

Upvotes: 7

Views: 7612

Answers (3)

wasmup
wasmup

Reputation: 16213

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).

Upvotes: 12

Jonathan Hall
Jonathan Hall

Reputation: 79546

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.

Upvotes: 12

gede nata
gede nata

Reputation: 39

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
}

Upvotes: 3

Related Questions