Home > Backend Development > Golang > 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
Release: 2024-10-30 17:43:02
Original
1000 people have browsed it

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
}
Copy after login

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)
}

...
Copy after login

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!

source:php.cn
Statement of this Website
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
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template