我正试图暂停并恢复日常工作。我知道我可以sleep
运行,但是我正在寻找的是按钮“暂停/恢复”而不是计时器。
这是我的尝试。我正在使用通道的阻止功能暂停,并使用select
根据通道值切换要执行的操作。但是,在我的情况下,输出始终为Running
。
func main() {
ctx := wctx{}
go func(ctx wctx) {
for {
time.Sleep(1 * time.Second)
select {
case <-ctx.pause:
fmt.Print("Paused")
<-ctx.pause
case <-ctx.resume:
fmt.Print("Resumed")
default:
fmt.Print("Running \n")
}
}
}(ctx)
ctx.pause <- struct{}{}
ctx.resume <- struct{}{}
}
type wctx struct {
pause chan struct{}
resume chan struct{}
}
具有多个就绪案例的select
,会随机选择一个伪随机数。因此,如果goroutine是“慢”的以检查那些通道,则可以在pause
和resume
上都发送一个值(假设它们已被缓冲),这样就可以准备从两个通道接收数据,并且可以先选择resume
,并且在以后的迭代中,[go]不应再暂停goroutine的pause
。
为此,您应该使用由互斥锁同步的“状态”变量。像这样的东西:
const (
StateRunning = iota
StatePaused
)
type wctx struct {
mu sync.Mutex
state int
}
func (w *wctx) SetState(state int) {
w.mu.Lock()
defer w.mu.Unlock()
w.state = state
}
func (w *wctx) State() int {
w.mu.Lock()
defer w.mu.Unlock()
return w.state
}
正在测试:
ctx := &wctx{}
go func(ctx *wctx) {
for {
time.Sleep(1 * time.Millisecond)
switch state := ctx.State(); state {
case StatePaused:
fmt.Println("Paused")
default:
fmt.Println("Running")
}
}
}(ctx)
time.Sleep(3 * time.Millisecond)
ctx.SetState(StatePaused)
time.Sleep(3 * time.Millisecond)
ctx.SetState(StateRunning)
time.Sleep(2 * time.Millisecond)
输出(在Go Playground上尝试):
Running
Running
Running
Paused
Paused
Paused
Running
Running
您需要初始化通道,请记住,从零个通道读取的数据始终会阻塞。
带有select
大小写的default
永远不会阻塞。
这里是程序的修改版本,可解决上述问题:
package main
import (
"fmt"
"time"
)
func main() {
ctx := wctx{
pause: make(chan struct{}),
resume: make(chan struct{}),
}
go func(ctx wctx) {
for {
select {
case <-ctx.pause:
fmt.Println("Paused")
case <-ctx.resume:
fmt.Println("Resumed")
}
fmt.Println("Running")
time.Sleep(time.Second)
}
}(ctx)
ctx.pause <- struct{}{}
ctx.resume <- struct{}{}
}
type wctx struct {
pause chan struct{}
resume chan struct{}
}