Home >Backend Development >Golang >How to Implement a Timeout for WaitGroup.Wait() in Go?

How to Implement a Timeout for WaitGroup.Wait() in Go?

Susan Sarandon
Susan SarandonOriginal
2024-11-12 17:17:01950browse

How to Implement a Timeout for WaitGroup.Wait() in Go?

Timeout for WaitGroup.Wait(): Idiomatic Approaches

In Go, a time limit can be set for WaitGroup.Wait() to prevent infinite waiting for errant workers. Here's a detailed exploration of idiomatic ways to implement it and alternative approaches.

Recommended Solution: Using a Timer and Channel

The following approach is widely considered the most idiomatic solution:

import (
    "sync"
    "time"
)

func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
    c := make(chan struct{})
    go func() {
        wg.Wait()
        close(c)
    }()
    select {
    case <-c:
        return false // completed normally
    case <-time.After(timeout):
        return true // timed out
    }
}
  • A channel (c) is created to signal when the wait group completes its wait.
  • A goroutine is spawned to call wg.Wait() and close the channel when finished.
  • A select statement listens for either the channel to be closed or a timeout to occur.
  • If the channel is closed, the function returns false, indicating normal completion.
  • If the timeout is reached, the function returns true, signifying a timeout.

Simplifying the Recommended Solution

For a simpler implementation, consider the following:

  • Close the channel to signal completion instead of sending a value.
  • Use defer to close the channel even if the function terminates prematurely.
  • Remove the wait group if only one job needs to be waited for.
  • Use time durations directly without conversions (e.g., time.Second).

Alternative Approach: Using a Cancellable Context

An alternative approach involves using a cancellable context:

import (
    "context"
    "sync/atomic"
    "sync"
)

func waitWithCancel(ctx context.Context, wg *sync.WaitGroup) bool {
    ctxDone := make(chan struct{})
    var exited int32
    go func() {
        defer close(ctxDone)
        wg.Wait()
        atomic.StoreInt32(&exited, 1)
    }()

    select {
    case <-ctx.Done():
        return atomic.LoadInt32(&exited) == 0
    case <-ctxDone:
        return true
    }
}
  • A cancellable context (ctx) is created.
  • A channel (ctxDone) is used to signal when the context is cancelled.
  • A goroutine is spawned to wait for the wait group and signal the ctxDone channel.
  • A select statement listens for either the context to be cancelled or the wait group to complete.
  • If the context is cancelled, the function returns based on whether the wait group had already finished its wait.

The above is the detailed content of How to Implement a Timeout for WaitGroup.Wait() 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