【问题标题】:Elixir GenServer.start_link throws exception instead of returning a tupleElixir GenServer.start_link 抛出异常而不是返回元组
【发布时间】:2016-09-08 10:31:33
【问题描述】:

我在玩GenServer,但在实现自定义init 回调时遇到问题。

请考虑以下代码:

defmodule GenS do
  use GenServer

  def start_link(initial \\ 0) do
    GenServer.start_link(__MODULE__, initial)
  end

  def init(initial) do
    case initial do
      3 -> {:stop, "Can't initialise with 3"}
      _ -> {:ok, initial}
    end
  end
end

case GenS.start_link(3) do
  {:error, reason} -> IO.puts "Failed with #{reason}"
  {:ok,    _}      -> IO.puts "This has worked!"
end

IO.puts "I'm still alive!"

执行此代码时,我可以看到输出:

▶ elixir gens.ex
** (EXIT from #PID<0.46.0>) "Can't initialise with 3"

虽然我期望 成功 分支有类似的输出(当值不同于 3 作为参数传递时):

▶ elixir gens.ex
This has worked!
I'm still alive!

根据GenServer.start_link/3的文档:

如果init/1 回调因原因失败,此函数将返回{:error, reason}。否则,如果返回{:stop, reason}:ignore,则终止进程,该函数分别返回{:error, reason}:ignore

我希望返回元组,我可以再次匹配,但似乎并非如此。你有什么建议吗?

【问题讨论】:

    标签: elixir gen-server


    【解决方案1】:

    我希望返回元组,我可以再次匹配,但似乎并非如此。你有什么建议吗?

    这里的问题是您将 链接到生成的进程并从 init 返回 {:stop, ...} 正在向调用进程发送退出信号,默认情况下会终止调用进程。

    您可以切换到使用GenServer.start(如果您愿意,可以稍后手动链接进程),或者通过在启动GenS之前运行以下命令来捕获退出信号:

    Process.flag(:trap_exit, true)
    

    (请注意,当GenS 死亡时,这将向调用进程发送一条消息,您可能希望将其丢弃以防止浪费内存。)

    在这两种情况下,我都会得到以下输出:

    Failed with Can't initialise with 3
    I'm still alive!
    

    【讨论】:

    • 这很有趣。谢谢你分享这个。事实证明,文档听起来令人困惑-基于此,我期望得到可以安全匹配的结果...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    相关资源
    最近更新 更多