Why? #
If you're looking at semaphores, there is a chance you've got some base concurrency going on and you're interested controlling access to a system across your multiple goroutines.
Maybe you've got 100 go routines and an api which can only handle 10 requests at a time.
The easy approach #
Fortunately in go, it's relatively easy to come up with a solution.
package main
import (
"fmt"
"sync"
)
func main() {
const apiLimit = 5
const numTasks = 10
// Create a buffered channel to implement the semaphore
semaphore := make(chan struct{}, apiLimit)
// WaitGroup to wait for all goroutines to finish
var wg sync.WaitGroup
// Simulated task function
task := func(i int) {
defer wg.Done()
// Acquire semaphore (block if the limit is reached)
semaphore <- struct{}{}
defer func() {
// Release semaphore
<-semaphore
}()
// do some work
}
// Start workers
for i := 0; i < numTasks; i++ {
wg.Add(1)
go task(i)
}
// Wait for all workers to finish
wg.Wait()
fmt.Println("All tasks completed.")
}