What are the ways to synchronize data in Go?
sobes.tech AI
Answer from AI
In Go, synchronization is primarily achieved through "structural concurrency," encouraging the use of channels for data exchange between goroutines instead of shared memory with explicit locking.
Main mechanisms:
-
Channels: Typed communication channels through which values can be sent and received. They can be buffered or unbuffered. Using channels is considered idiomatic in Go for synchronizing access to data and coordinating goroutines.
// Unbuffered channel ch := make(chan int) // Buffered channel bufferedCh := make(chan string, 10) // Sending to a channel go func() { ch <- 1 }() // Receiving from a channel val := <-ch -
Package
sync: Provides synchronization primitives for more traditional shared memory scenarios.-
Mutex: Mutual exclusion lock. Only one owner at a time.
import "sync" var mu sync.Mutex var balance int func deposit(amount int) { mu.Lock() balance += amount mu.Unlock() } -
RWMutex: Read/write mutex. Allows multiple goroutines to read simultaneously, but only one to write.
import "sync" var rwmu sync.RWMutex var data map[string]string func readData(key string) string { rwmu.RLock() // Lock for reading defer rwmu.RUnlock() return data[key] } func writeData(key, value string) { rwmu.Lock() // Lock for writing defer rwmu.Unlock() data[key] = value } -
WaitGroup: Waits for a group of goroutines to finish.
import "sync" var wg sync.WaitGroup func worker() { defer wg.Done() // Decrement counter on completion // Goroutine work } func main() { wg.Add(5) // Increment counter for i := 0; i < 5; i++ { go worker() } wg.Wait() // Wait until counter is zero } -
Once: Ensures a specific action is performed only once.
import "sync" import "fmt" var once sync.Once func setup() { fmt.Println("Executed only once") } func main() { go func() { once.Do(setup) }() go func() { once.Do(setup) }() // Both goroutines call once.Do(setup), but setup will only run once }
-
In conclusion, channels are preferred for their safer and more understandable concurrency models. However, for certain scenarios, such as protecting shared data structures, primitives from the sync package are suitable.