Sobes.tech
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.