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_number 和 initial_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/3
和handle_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_number
call
时,它会按照前面的步骤,除了内部状态现在是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的主要内容,如果未能解决你的问题,请参考以下文章