# Goroutines and Their Lifecycle — Go Concurrency Patterns

Source: https://www.geekswithgeeks.com/en/go-concurrency/gc-goroutines

> Starting is easy; knowing who stops a goroutine is the real design question.

## Every goroutine needs an exit

The `go` keyword starts a function call in a new goroutine and returns immediately; there is no handle to join or kill it. A goroutine ends only when its function returns (or the whole program exits: when `main` returns, all other goroutines are abandoned mid-flight). Goroutines start with small, growable stacks, so creating thousands is normal, but each one still holds memory and anything it references until it returns. Therefore, whenever you write `go`, answer two questions: **how will this goroutine stop**, and **who waits for it to finish**? Typical answers are a closed channel, a cancelled `context.Context`, and a `sync.WaitGroup` or `errgroup.Group` that the caller waits on.

## A goroutine with an explicit stop signal

The caller owns both the stop channel and the wait.

```go
package main

import (
	"fmt"
	"sync"
	"time"
)

func heartbeat(stop <-chan struct{}, wg *sync.WaitGroup) {
	defer wg.Done()
	t := time.NewTicker(100 * time.Millisecond)
	defer t.Stop()
	for {
		select {
		case <-stop:
			fmt.Println("heartbeat: stopping")
			return
		case <-t.C:
			fmt.Println("beat")
		}
	}
}

func main() {
	stop := make(chan struct{})
	var wg sync.WaitGroup
	wg.Add(1)
	go heartbeat(stop, &wg)

	time.Sleep(350 * time.Millisecond)
	close(stop) // broadcast "stop" to the goroutine
	wg.Wait()   // and wait until it has actually returned
}
```

## Never fix ordering with time.Sleep

Sleeping in main "to let goroutines finish" is a race that happens to pass on your machine. Use a WaitGroup, a channel or errgroup to wait for completion explicitly.

**Quiz:** What happens to running goroutines when main returns?

- [x] The program exits and they are stopped without running further code
- [ ] main waits for them automatically
- [ ] They keep running in the background as a daemon
- [ ] The runtime panics with a deadlock error

*Answer:* The program exits and they are stopped without running further code. Program exit does not wait for goroutines and does not run their deferred calls; you must wait for them explicitly.
