1

I am new to Golang and starting to use goroutines. I am curious if it is safe to read from a data structure that is being written to by another goroutines without using channel or mutex. In the example below, the events array is visible to main and goroutine, but main only reads from it and the goroutine is modifying it. Is this considered safe?

var events = []string{}

func main() {

    go func() {
        for {
            if len(events) > 30 {
                events = nil
            }
            event := "The time is now " + time.Now().String()
            events = append(events, event)
            time.Sleep(time.Millisecond * 200)
        }
    }()

    for {
        for i:=0; i < len(events); i++ {
            fmt.Println(events[i])
        }
        time.Sleep(time.Millisecond * 100)
        fmt.Println("--------------------------------------------------------")
    }
}

Thanks.

raminr
  • 784
  • 3
  • 12
  • 2
    No concurrent read + write is ever safe. Such code is racy and undefined under each and every condition. – Volker Oct 18 '20 at 16:42

1 Answers1

1

No, this is absolutely not safe. You should use synchronization primitives around access to events, or redesign to use channels.

Your code may work fine today, on a specific architecture/OS, but it may break unexpectedly with small changes and/or on another architecture/OS.

Try to run your code with -race to verify. You'll probably see WARNING: DATA RACE.

See also this answer.

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
  • Thanks. You are right in that given the current state, no race conditions happen. But after thinking about it, I realized it could easily happen when main is looping over events and the memory address location could be invalid if my event list is long enough and a context switch happens during the loop. – raminr Oct 18 '20 at 17:38