Concurrency · 3 MIN READ

go returns nothing

Get a result out of a goroutine, and know when the program stops waiting.

go f() starts f and immediately continues. There is no future to await and no value to collect, so the result has to come back through a channel or a shared variable protected by something.

The second half matters just as much: when main returns, the program exits and every remaining goroutine simply stops. A goroutine still blocked at that moment did not fail — it was never finished.

SEE THE IDEA

Starting work is separate from waiting for it

  1. 01

    Start

    go
    go work()

    Begins a goroutine; returns no handle

  2. 02

    Coordinate

    go
    done := make(chan struct{})

    Choose a completion signal

  3. 03

    Wait

    go
    <-done

    Observe completion explicitly

A go statement does not provide an implicit join or keep main alive.

In practice

Pick a completion contract before starting a goroutine. A closed channel can signal one operation’s completion; a WaitGroup can join several operations. Pass cancellation and result paths deliberately so a caller can stop and collect the work it starts.

Watch out

When main returns, the program exits even if other goroutines have unfinished work.

Official reference ↗

Read and predict

go
package main

import "fmt"

func main() {
	results := make(chan int)
	go func() { results <- 42 }()
	go func() { fmt.Println("this may never print") }()
	fmt.Println(<-results)
}

Is the second goroutine guaranteed to print?

Try it yourself

Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.

Progress stays in this browser. No account needed.