Elixir 理解 GenServer

Posted

技术标签:

【中文标题】Elixir 理解 GenServer【英文标题】:Elixir understanding GenServer 【发布时间】:2018-12-14 20:00:09 【问题描述】:

我是 Elixir 的新手,正在阅读一本书并做了一些示例。这是让我在这里提问的一段代码:

defmodule Sequence.Server do
    use GenServer
    def init(initial_number)do 
        :ok,initial_number
    end

    def handle_call(:next_number, _from, current_number)do
        :reply, current_number,current_number+1    
    end 
end

据我所知,init 函数在服务器初始化时被调用,我们正在定义一些参数 - 这将是服务器的初始状态。让我感到困惑的是 current_numberinitial_number 是如何相互关联的,我的意思是在我们所说的代码中没有任何地方

current_number = initial_number

因为当我调用GenServer.call(some_process_id, :next_number) 时,它从 100 开始,例如,如果 start_link 的参数是 100。当我们在初始值之间没有任何映射时,Elixir 如何理解它必须从 100 开始状态和current_number 参数

【问题讨论】:

希望对你有帮助codefather.org/erlang-generic-behaviors 我想推荐一本伟大的 LYSE 书,特别是章节 learnyousomeerlang.com/more-on-multiprocessing 和 learnyousomeerlang.com/what-is-otp 和 learnyousomeerlang.com/clients-and-servers 以了解如何编写 gen_server(和其他 gen_* 抽象)。强烈推荐阅读整本书,这也很有趣:) 谢谢大家:) 【参考方案1】:

init/1 的目的是设置GenServer 的内部状态。修改此GenServer 内部状态的唯一方法是通过call-ing、cast-ing 或发送常规消息(然后由handle_info/2 回调处理)。

这些函数(分别为handle_call/3handle_cast/2)将使用GenServer 的内部状态作为函数参数的最后一个参数传入。

考虑场景:

    您正在使用编号 100 初始化 GenServer。 您向此GenServer - :next_number 发送消息(更具体的call)。 这会调用您的handle_call(:next_number, _from, current_number) 回调函数,其中current_number 的初始值为100。 作为此函数的返回值,您指定了元组::reply, current_number,current_number+1,您应该理解为:reply(元组的第一个元素)表示它将回复调用者;元组的第二个元素将是返回给调用者的值(在这种情况下,它将是数字100);元组的最后一个元素将是 GenServer 的新状态 - current_number+1,因此是 101。 当你向这个GenServer发送另一个:next_numbercall时,它会按照前面的步骤,除了内部状态现在是101,从函数返回后,新的状态将是102等...

【讨论】:

【参考方案2】:

init 的结果是:ok, initial_state,其中状态值GenServer 持有

handle_call的签名实际上是handle_call(request, from, current_state),它返回:reply, result, new_state

这意味着当您执行GenServer.call(pid, :next_number) 时,会调用handle_call(:next_number, _from, state),其中状态(以current_number 传递)以initial_number 开头,handle_call 的结果会保存一个新的状态值为current_number

下次你调用GenServer.call(pid, :next_number)时,它会以新状态调用,然后你返回新状态,以此类推...

【讨论】:

以上是关于Elixir 理解 GenServer的主要内容,如果未能解决你的问题,请参考以下文章

Erlang vs Elixir 宏

混合 Elixir 和 Erlang?

Laravel_Elixir_gulp任务利器安装

Elixir Operator重载:使用宏定义独占范围

“pin”操作符是干啥用的,Elixir 变量是可变的吗?

Elixir / JInterface - 从 Java 将字符串列表发送回 elixir