Skip to content

Instantly share code, notes, and snippets.

@Integralist
Created December 20, 2024 12:32
Show Gist options
  • Save Integralist/bd107aa44b01e6f2077861bf746e4664 to your computer and use it in GitHub Desktop.
Save Integralist/bd107aa44b01e6f2077861bf746e4664 to your computer and use it in GitHub Desktop.
[Golang Single-Flight] #go #golang #singleflight #requestcollapsing #sync
// https://play.golang.com/p/GoyqwZ5jW_L
// https://pkg.go.dev/golang.org/x/sync/singleflight
// https://victoriametrics.com/blog/go-singleflight/index.html
package main
import (
"fmt"
"math/rand"
"sync"
"sync/atomic"
"time"
"golang.org/x/sync/singleflight"
)
var callCount atomic.Int32
var wg sync.WaitGroup
// Simulate a function that fetches data from a database
func fetchData() (interface{}, error) {
callCount.Add(1)
time.Sleep(100 * time.Millisecond)
return rand.Intn(100), nil
}
// Wrap the fetchData function with singleflight
func fetchDataWrapper(g *singleflight.Group, id int) error {
defer wg.Done()
time.Sleep(time.Duration(id) * 40 * time.Millisecond)
v, err, shared := g.Do("key-fetch-data", fetchData)
if err != nil {
return err
}
fmt.Printf("Goroutine %d: result: %v, shared: %v\n", id, v, shared)
return nil
}
func main() {
var g singleflight.Group
// 5 goroutines to fetch the same data
const numGoroutines = 5
wg.Add(numGoroutines)
for i := 0; i < numGoroutines; i++ {
go fetchDataWrapper(&g, i)
}
wg.Wait()
fmt.Printf("Function was called %d times\n", callCount.Load())
}
// Output:
// Goroutine 0: result: 90, shared: true
// Goroutine 2: result: 90, shared: true
// Goroutine 1: result: 90, shared: true
// Goroutine 3: result: 13, shared: true
// Goroutine 4: result: 13, shared: true
// Function was called 2 times
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment