Quick Start

This guide will walk you through a minimal example of using conc to manage concurrent goroutines. We'll use conc.WaitGroup to run several tasks in parallel and wait for them to complete.

conc.WaitGroup is a safer alternative to sync.WaitGroup because it automatically recovers from panics in child goroutines and propagates them to the caller of Wait().

Example: Concurrent Counter

Here is a complete, runnable example that starts 10 goroutines to increment a counter. The main function waits for all of them to finish before printing the final value.

package main

import (
    "fmt"
    "sync/atomic"

    "github.com/sourcegraph/conc"
)

func main() {
    // A counter that we will increment concurrently.
    // We use atomic operations to prevent race conditions.
    var count atomic.Int64

    // Declare a conc.WaitGroup. Its zero value is ready to use.
    var wg conc.WaitGroup

    // Start 10 goroutines.
    for i := 0; i < 10; i++ {
        // wg.Go() starts a new goroutine and manages its lifecycle.
        // It's like `go f()` but with panic handling and automatic tracking.
        wg.Go(func() {
            count.Add(1)
        })
    }

    // wg.Wait() blocks until all goroutines started with wg.Go() have completed.
    // If any of the goroutines panicked, Wait() will re-panic with the captured panic value.
    wg.Wait()

    // Print the final count.
    fmt.Println(count.Load())
}

How to Run

  1. Save the code above as main.go.
  2. Make sure you have conc installed:
    go get github.com/sourcegraph/conc
  3. Run the program:
    go run main.go

Expected Output

10

This simple example demonstrates the core principle of structured concurrency in conc: every goroutine is owned, and the owner waits for it to complete. This prevents leaked goroutines and ensures that program state is consistent.