我有一个应该永远持续的异步进程,看起来是这样的:

func asyncForeverTask() {
  for {
    anyTask()
  }
}

func main() {
  go asyncForeverTask()

  server.run(8080)
}

当某个请求请求到达服务器时,我希望能够停止此for循环.

我知道我需要使用context.WithCancel(),但我不知道如何整合它才能工作.我知道以下语法:

for {
  select {
  case <-ctx.Done:
    return
  case <-otherCh:
    // do smh.
  }
}

asyncForeverTask不是由任何其他CH发出的信号运行的,而是永远运行.我是个菜鸟,任何类型的帮助我都会很感激.

推荐答案

您可以使用频道执行此操作:

var stopAsync = make(chan struct{})

func asyncForeverTask() {
  for {
    select {
      case <-stopAsync:
         return
      default:
    }
    anyTask()
  }
}

要取消,只需关闭频道即可.你必须确保频道只关闭一次,否则你会panic 的.

您也可以在有上下文的情况下执行此操作:

func main() {
   ctx,cancel:=context.WithCancel(context.Background())
   go asyncForeverTask(ctx)
   ...
}

func asyncForeverTask(ctx context.Context) {
  for {
    select {
      case <-ctx.Done():
         return
      default:
    }
    anyTask()
  }
}

或者:

func asyncForeverTask(ctx context.Context) {
  for {
    if ctx.Err()!=nil {
       return
    }
    anyTask()
  }

要停止,请调用返回的cancel函数:

...
cancel()

如果您还需要停止anyTask,您必须经常判断通道关闭或上下文关闭,然后从任务返回.

Go相关问答推荐

向API网关终结点发出POST请求时出现AWS Lambda With Go:";Rune me.InvalidEntrypoint";错误

使用一元或服务器流将切片从GRPC服务器返回到客户端

允许在 struct 中使用复合作为函数参数

迭代字符串并用映射值替换原始字符串中的值的惯用方法

Golang 网络应用程序安全性:您是否应该判断输入是否为有效的 utf-8?

如何使用 GolangCI 删除未使用的导入

如何从 Go 中的 `HijackedResponse` 中删除 Cursor Position ANSI 转义码?

Go Colly 如何找到请求的元素?

如果 transaction.Commit 对带有 postgres 连接的 SQL 失败,您是否需要调用 transaction.RollBack

级联调用泛型函数时的泛型类型推断

如何在Go中替换符号并使下一个字母大写

Ginkgo/Gomega panic 测试失败

Go lang - 惯用的默认后备

如何在 Unmarshal 中使用泛型(转到 1.18)

退格字符在围棋操场中不起作用

如何获得Ent中数字列的总和

Scanner.Buffer - 最大值对自定义拆分没有影响?

如何使用 httputil.ReverseProxy 设置 X-Forwarded-For

如何在 Prometheus 中正确检测区域和环境信息?

如何在程序退出时使用 golang 删除文件?