Derptacos
Derptacos

Reputation: 177

Golang/Gopher way to manipulate data in different channels?

New to go and to make sure Im on the right page with channels + concurrency I have a struct

type Playlist struct {
  playList   []*Song
  updateList chan *Song
}

I have 2 functions that manipulate the data in separate go routines.

First one is to append data to the playlist whenever a pointer to a song is sent on the channel:

  func (p *Playlist) continuousUpdate() {
    go func (){
      for newSong := range p.updateList {
        p.playlist = append(p.playlist, newSong)
      }
    }()
  }

And the second one, every 24 hours a timer will tick, thus resetting the playlist to an empty slice.

func (p *Playlist) controlCurrentPlayList(c <-chan time.Time) {
  go func(){
    for {
      <-c
      p.playlist = make([]*Song, 0)
      log.Println("Current playlist has reset")
    }
  }()
}

Do two separate channels handle the synchronization of the data? Or could I very easily run into a race condition?

Ran go build -race and no errors appeared.

Upvotes: 0

Views: 202

Answers (1)

Thundercat
Thundercat

Reputation: 121109

Because the field playlist is accessed from two goroutines with no synchronization, there is a race.

The race detector detects races at runtime, not build time. This race will not be detected until the 24 hour reset timer ticks.

The race can be eliminated by combining the two goroutines using a select statement:

for {
    select {
    case newSong := <-p.updateList:
        p.playlist = append(p.playlist, newSong)
    case <-c:
        p.playlist = make([]*Song, 0)
        log.Println("Current playlist has reset")
    }
 }

Upvotes: 6

Related Questions