Senior
// Task 3 // Describe what problem this code solves // What problems are there in this solution? // How would you rewrite this code? var c int var mu sync.RWMutex type Trace struct { // Some fields here } type Sender interface { Send(Trace) } func Do(sender Sender, tr Trace) { mu.Lock() defer mu.Unlock() c++ if c == 100 { go func() { sender.Send(tr) }() c = 0 } }
sobes.tech AI
Answer from AI
This code attempts to count calls to the Do function and, upon reaching 100, calls the Send method of the Sender interface in a separate goroutine, then resets the counter.
Problems:
- Uses a global variable c and a mutex mu, which creates a bottleneck and reduces parallelism.
- The call to sender.Send(tr) occurs in a goroutine, but tr is passed by value, which can lead to data desynchronization.
- Resetting the counter c = 0 happens inside a locked section, which can cause delays.
- No error handling or confirmation of successful sending.
How to rewrite:
- Use an atomic counter instead of a mutex for better performance.
- Move the Send call outside the critical section.
- Possibly use a channel to pass data to a dedicated worker that handles sending.
Example of an improved version:
var c int32
type Trace struct {
// fields
}
type Sender interface {
Send(Trace)
}
func Do(sender Sender, tr Trace) {
newCount := atomic.AddInt32(&c, 1)
if newCount == 100 {
atomic.StoreInt32(&c, 0)
go sender.Send(tr)
}
}
Or better organize a queue and a dedicated worker for sending to avoid races and locks.