Semaphore

· go's blog


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