core.async 怎么办 >!函数验证它是否从 go 块内部调用

How does the core.async >! function verify if its being called from inside of a go block

在 core.async 中,如果您在 go 块之外调用 >! 函数,它会抛出错误 <! used not in (go ...) block。该函数如何知道它没有在 go 块内执行?我需要创建一些非常相似的东西,我需要确保只能从宏内部调用函数。我该如何处理?我查看了 core.async 来源,但我无法真正弄清楚它是如何工作的。

这是 <! 的源代码:

(defn <!
  "Takes a value from the channel. Must be called inside a (go ...) block. Will
  return nil if closed. Will park if nothing is available."
  [port]
  (assert nil "<! used not in (go ...) block"))

请注意,assert 会为任何虚假值抛出异常,因此如果您在 go 块之外使用 <!,则会收到此错误消息。

当您使用 go 宏时,它会递归地遍历它包含的所有代码表达式, 替换 等符号<! 其他代码 不调用上面显示的 "error case" 代码。

除了 Alan Thompson 的回答之外还有代码(go 宏) 将符号 替换为 <! 等其他不调用 错误案例:

还有 [clojure.core.async.impl.ioc-macros :as ioc] 命名空间用于此目的。

   (dispatch/run
     (^:once fn* []
      (let [~@(mapcat (fn [[l sym]] [sym `(^:once fn* [] ~(vary-meta l dissoc :tag))]) crossing-env)
            f# ~(ioc/state-machine `(do ~@body) 1 [crossing-env &env] ioc/async-custom-terminators)
            state# (-> (f#)
                       (ioc/aset-all! ioc/USER-START-IDX c#
                                      ioc/BINDINGS-IDX captured-bindings#))]
        (ioc/run-state-machine-wrapped state#))))