为 core.async 个频道拉取而不是推送?

pull instead of push for core.async channels?

我想知道为什么来自 core.async 通道的数据是通过无限循环的拉取机制检索的。例如:

user=> (def c (chan 1))
#'user/c

user=> (go-loop []
         (let [x (<! c)]
           (println "Got a value in this loop:" x))
         (recur))

#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@30df0e27>

参考:https://clojuredocs.org/clojure.core.async/go-loop#example-542c88e3e4b05f4d257a297b

为什么没有我可以挂钩的推送机制?或者为什么这样的循环不是 core.async 订阅者的一些实现细节? 我认为拥有一个无休止的 运行 机制非常 cpu 消耗。不是这样吗?

core.async/go 的文档字符串说:

Asynchronously executes the body, returning immediately to the calling thread. Additionally, any visible calls to ! and alt!/alts! channel operations within the body will block (if necessary) by 'parking' the calling thread rather than tying up an OS thread (or the only JS thread when in ClojureScript). Upon completion of the operation, the body will be resumed. Returns a channel which will receive the result of the body when completed

如果go在队列中等待新消息的时候没有停放,那么循环在CPU上确实很浪费。但是,当 go 循环到达 <! 时,它将暂停线程,并且只有在可从队列中获取值时才会恢复。