Home  >  Article  >  Backend Development  >  Why Does a `sync.WaitGroup` and Channel Combination Lead to a Deadlock in Go?

Why Does a `sync.WaitGroup` and Channel Combination Lead to a Deadlock in Go?

Susan Sarandon
Susan SarandonOriginal
2024-10-30 17:43:02929browse

Why Does a `sync.WaitGroup` and Channel Combination Lead to a Deadlock in Go?

Understanding Deadlocks when using sync.WaitGroup and Channels in Go

Developers often encounter issues with their Go applications never exiting when utilizing sync.WaitGroup and channels. This article explores the reasons behind such deadlocks and offers a solution using the WaitGroup.

Consider the example code provided:

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
    "sync"
)

var symbols = []string{
    "ASSA-B.ST",
    "ELUX-B.ST",
    "HM-B.ST",
}

func main() {

    fmt.Println("fetching quotes...")

    fetchedSymbols := make(chan string)
    var wg sync.WaitGroup
    wg.Add(len(symbols))

    for _, symbol := range symbols {
        go fetchSymbol(symbol, &wg, fetchedSymbols)
    }

    for response := range fetchedSymbols {
        fmt.Println("fetched " + response)
    }

    wg.Wait()

    fmt.Println("done")

}

func fetchSymbol(symbol string, wg *sync.WaitGroup, c chan<- string) {
    defer wg.Done()
    resp, err := http.Get("http://ichart.yahoo.com/table.csv?s=" + symbol + "&amp;a=0&amp;b=1&amp;c=2000")
    defer resp.Body.Close()

    if err != nil {
        log.Fatal(err)
    }

    out, err := os.Create("./stock-quotes/" + symbol + ".csv")
    defer out.Close()

    if err != nil {
        log.Fatal(err)
    }

    io.Copy(out, resp.Body)
    c <- symbol
}

In this code, the range loop over fetchedSymbols will block the main function indefinitely. Why? Because the fetchedSymbols channel is never closed. To resolve this deadlock, the WaitGroup can be used to signal when to close the channel:

...
go func() {
    wg.Wait()
    close(fetchedSymbols)
}()

for response := range fetchedSymbols {
    fmt.Println("fetched " + response)
}

...

As the WaitGroup already tracks when all goroutines have completed, it can be leveraged to trigger the closing of the fetchedSymbols channel, ensuring the range loop terminates gracefully.

The above is the detailed content of Why Does a `sync.WaitGroup` and Channel Combination Lead to a Deadlock in Go?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn