3

I'm currently reading the slices of Go Concurrency Patterns. I'm a little bit confused about a seeming contradiction between a statement on slide #16:

When main returns, the program exits and takes the boring function down with it.

and another one on slide #19 (in combination with the example on slide #20):

A channel in Go provides a connection between two goroutines, allowing them to communicate.

If main is just a goroutine, how can it cause any another (spawned) goroutine to stop, in other words: in what sense is the goroutine named main special?*


* I searched for it, but found nothing obviously enlightening so far; the SO question with the promising title Difference between the main goroutine and spawned goroutines of a Go program asks for a completely different issue.

edit: changed the title, to focus on the difference between main and "normal" goroutines (after stumbling upon the Go runtime function Goexit)

edit: simplified question, to be even more focused on the specifics of main

Wolf
  • 9,679
  • 7
  • 62
  • 108
  • 3
    What do you mean by "how can it take control over another goroutine," ? There's does not appear to be any mentioning of a goroutine taking control over something else . Note that when the program returns from main(), the entire process dies/exits. main() is almost "just" a gouroutine. But it's special since naturally this is where execution of the entire program starts (besides any init() functions being run), and when main() ends, the process dies. – nos Dec 15 '16 at 11:54
  • @nos I tried to clarify this in the question, if it's simply bad English, please help me non-native speaker. – Wolf Dec 15 '16 at 12:09
  • @nos *`...almost "just" a gouroutine. But it's special since...`* exactly what I'm asking for (can you explain this in more detail?). The first example in the slides shows a channeled communication between main and another goroutine. I was interested in more details, because I compare this with threads in Windows (there the idea is each thread is equivalent in the sense that i can keep the process running, but each of it can exit the process). (I already know: goroutines are not threads, but by comparison I hope to understand the concept better) – Wolf Dec 15 '16 at 12:16
  • 3
    The runtime will make a goroutine and call main with it. When main returns, the runtime will exit. It's like with most programming languages: returning from main exits the program, irrespective of any threads you might have spawned. – Alexander Torstling Dec 15 '16 at 12:18
  • 1
    Who said `main` is a goroutine? – RickyA Dec 15 '16 at 12:18
  • @RickyA I deduced this from #19 and #20, maybe I'm completely wrong... – Wolf Dec 15 '16 at 12:20
  • I did! Who said anything else? – Alexander Torstling Dec 15 '16 at 12:21
  • @AlexanderTorstling Interesting, just what I guessed. Have you a good reference for that? Would you mind explaining this as an answer? :) – Wolf Dec 15 '16 at 12:24
  • Any`goroutine` can spawn another `goroutine`. Before spawning another one, you can setup a channel. Then either by passing a reference, or using closurers, the new spawned `goroutine` can utilitze that defined channel. Main() does not control other `goroutines`, it simply just defines a channel and spawns another - just like you can do in any oyher function or `goroutine`>. – eduncan911 Dec 15 '16 at 12:36
  • 2
    @RickyA, I am a newbie and you are confusing me now! The book I am reading (Programming in Go - Mark Summerfield) says this "A goroutine is a function or method invocation that executes independently and concurrently in relation to any other goroutines in a program. Every Go program has at least one goroutine, the main goroutine in which the main package’s main() function executes. ...". – Cetin Basoz Dec 15 '16 at 12:36
  • @RickyA, main is a goroutine – JimB Dec 15 '16 at 13:07
  • 1
    @Wolf: See https://www.golang-book.com/books/intro/10 , "The first goroutine is implicit and is the main function itself". – Alexander Torstling Dec 15 '16 at 13:40
  • @AlexanderTorstling thanks :) I just found out a way to [retrieve the callers](http://stackoverflow.com/q/35212985/2932052) of `main`... BTW: do you see a real chance to get the question answered before it's getting closed? – Wolf Dec 15 '16 at 13:44
  • Main is only special in that it's called from the runtime, followed by a call to exit. Otherwise it's just a goroutine, just like any others. No goroutines "take control" of any others. – JimB Dec 15 '16 at 14:31
  • @JimB Well, it's *called* not started via `go`. – Wolf Dec 15 '16 at 14:36
  • 1
    Sorry, the main package's "main()" is called _from_ the main goroutine, which is called the same, and labeled as such in runtime/proc.go, documented as: `// The main goroutine.` – JimB Dec 15 '16 at 14:41
  • @JimB Yes, I found that [by experiment](https://play.golang.org/p/fMHHuehbXd) – Wolf Dec 15 '16 at 14:54
  • Possible duplicate of [Is the main function a goroutine?](https://stackoverflow.com/questions/53388154/is-the-main-function-a-goroutine) – Jonathan Hall Dec 29 '18 at 20:22

1 Answers1

4

I think you need to consider the goroutine implications separately to the process implications.

The main() function is a goroutine (or if you want to be really picky, called from an implicitly created goroutine). Using go creates other goroutines. Returning from main() terminates its goroutine but also terminates the process as a whole (and thus all other goroutines). It is also possible to terminate the process as a whole by calling os.Exit() or similar from any goroutine.

abligh
  • 24,573
  • 4
  • 47
  • 84
  • 1
    *`It is also possible to terminate the process as a whole by calling os.Exit() or similar from any goroutine.`* -- thanks for mentioning this detail, this would have been my next question (don't panic, not on SO ;) ) – Wolf Dec 15 '16 at 22:36
  • Worth noting that it's also totally possible to terminate the `main()` function goroutine without terminating the program (assuming there are other goroutines active), by using [`runtime.Goexit()`](https://golang.org/pkg/runtime/#Goexit). – Kaedys Dec 15 '16 at 23:06
  • @Kaedys *`runtime.Goexit()`* <-- this I found to be not recommended, since there is not a clean process exit after the last spawned coroutine returns. ("If all other goroutines exit, the program crashes.", see the reference you gave) – Wolf Dec 15 '16 at 23:22
  • 1
    @Wolf true, but if you can arrange for another go-routine to call `os.Exit()`, I think it's safe. – abligh Dec 16 '16 at 10:50
  • 1
    @Wolf oh, for sure. Not saying it's a _clean_ way of handling it, just pointing out that the main routine works just like any other routine in terms of being able to terminate it without implicitly terminating the process as a whole. – Kaedys Jan 05 '17 at 20:00
  • Your "really pick" remark is really missing the point. That's not being really picky--it's being fundamentally correct. functions and goroutines are categorically different types of concepts, so calling `main()`, or any function, a goroutine, is just plainly wrong. – Jonathan Hall Dec 29 '18 at 20:36