Sobes.tech
Junior

Live coding: Go tasks — concurrent requests, closures in goroutines, duplicate filtering, thread-safe counter, buffered channels, function timeout

sobes.tech AI

Answer from AI

In Go, it is often necessary to write concurrent code with goroutines and channels. Let's consider key points:

  1. Concurrent requests — you can launch multiple goroutines, each performing a request, and collect results through a channel.

  2. Closures in goroutines — it is important to correctly capture loop variables to avoid errors with shared state.

  3. Filtering duplicates — you can use a map to track already encountered values.

  4. Thread-safe counter — use sync.Mutex or atomic operations.

  5. Buffered channels — allow sending multiple values without blocking the sender.

  6. Function timeout — implemented via select with time.After.

An example that combines several of these aspects:

package main

import (
    "fmt"
    "sync"
    "time"
    "math/rand"
)

func main() {
    // Buffered channel for results
    results := make(chan int, 5)
    var wg sync.WaitGroup

    // Thread-safe counter
    var mu sync.Mutex
    counter := 0

    // Set for filtering duplicates
    seen := make(map[int]bool)

    // Launch 5 concurrent goroutines
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()

            // Closure with copy of id
            time.Sleep(time.Duration(rand.Intn(500)) * time.Millisecond)
            value := id * 10

            // Send result to channel with timeout
            select {
            case results <- value:
                // Increment counter safely
                mu.Lock()
                counter++
                mu.Unlock()
            case <-time.After(300 * time.Millisecond):
                fmt.Printf("Goroutine %d: timeout when sending\n", id)
            }
        }(i)
    }

    // Close channel after all goroutines finish
    go func() {
        wg.Wait()
        close(results)
    }()

    // Read from channel and filter duplicates
    for val := range results {
        if !seen[val] {
            fmt.Println("Received unique value:", val)
            seen[val] = true
        } else {
            fmt.Println("Duplicate skipped:", val)
        }
    }

    fmt.Println("Total unique values sent:", counter)
}

This example demonstrates:

  • Launching concurrent goroutines with closure (copy of id in function parameter).
  • Using a buffered channel to collect results.
  • Timeout when sending to the channel.
  • Thread-safe increment of the counter.
  • Filtering duplicates when reading from the channel.

This approach is often used for parallel processing and result collection with time and safety controls.