-2

I have 2 goroutines, g is used to detect the condition when f should stop, f checks whether it should stop in each iteration before doing the actual processing. In other languages such as Java, I would use a thread-safe shared variable, like the following code:

func g(stop *bool) {
  for {
    if check_condition() {
      *stop = true
      return
    }
  }
}

func f(stop *bool) {
  for {
    if *stop {
      return
    }
    do_something()
  }
}

func main() {
  var stop = false
  go g(&stop)
  go f(&stop)
  ...
}

I know the code above is not safe, but if I use channel to send stop from g to f, f would be blocked on reading from the channel, this is what I want to avoid. What is the safe and idiomatic way of doing this in Go?

Dagang
  • 24,586
  • 26
  • 88
  • 133

2 Answers2

2

Use channel close to notify other goroutines of a condition. Use select with a default clause to avoid blocking when checking for the condition.

func g(stop chan struct{}) {
    for {
        if check_condition() {
            close(stop)
            return
        }
    }
}

func f(stop chan struct{}) {
    for {
        select {
        case <-stop:
            return
        default:
            do_something()
        }
    }
}

func main() {
    var stop = make(chan struct{})
    go g(stop)
    go f(stop)
}

It also works to send a value to a channel with capacity greater than zero, but closing the channel extends to supporting multiple goroutines.

Charlie Tumahai
  • 113,709
  • 12
  • 249
  • 242
1

The way is to use a select statement with a default clause (see this example).

So f would look something like:

func f(stop chan bool) {
  select {
    case s := <- stop:
      if s {
        return
      }
    default:
      do_something()
  }
}
see sharper
  • 11,505
  • 8
  • 46
  • 65