Краткий ответ: да .
Мы можем упростить часть кода, чтобы понять суть почему. Рассмотрим вашу Mu
структуру:
type Mu struct {
memo int
done chan bool
}
Теперь мы можем определить 2 функции, compute
и read
func compute(r *Mu) {
time.Sleep(2 * time.Second)
r.memo = 42
close(r.done)
}
func read(r *Mu) {
<-r.done
fmt.Println("Read value: ", r.memo)
}
Здесь compute
- сложная вычислительная задача (которую мы можем смоделировать, поспав некоторое время)
Теперь в основной функции мы запускаем новую compute
подпрограмму go вместе с запуском некоторых read
подпрограмм go с регулярными интервалами:
func main() {
r := &Mu{}
r.done = make(chan bool)
go compute(r)
// this one starts immediately
go read(r)
time.Sleep(time.Second)
// this one starts in the middle of computation
go read(r)
time.Sleep(2*time.Second)
// this one starts after the computation is complete
go read(r)
// This is to prevent the program from terminating immediately
time.Sleep(3 * time.Second)
}
Во всех трех случаях мы распечатываем результат задачи вычисления.
Рабочий код здесь
Когда вы «закрываете» канал в go, все операторы, которые ожидают результата канала (включая операторы, которые выполняются после его закрытия), блокируются. Таким образом, при условии, что место only , от которого закрывается канал, является местом, где вычисляется значение памятки, у вас будет эта гарантия.
Единственное место, где вы должны быть осторожны, это убедиться, что этот канал не закрыт нигде в вашем коде.