Elixir了解GenServer

时间:2018-07-06 08:52:59

标签: functional-programming erlang elixir otp gen-server

我是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 是如何相互关联的,我的意思是在代码中没有我们在说这样的话

  

当前编号=初始编号

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

2 个答案:

答案 0 :(得分:7)

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

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

考虑场景:

  1. 您正在用数字GenServer初始化100
  2. 您为此call-GenServer发送了一条消息(更具体地说是:next_number
  3. 这会调用您的handle_call(:next_number, _from, current_number)回调函数,其中current_number的初始值为100
  4. 作为该函数的返回值,您指定了元组{:reply, current_number,current_number+1},您应该理解该元组:reply(元组的第一个元素)表示它将回复调用方;元组的第二个元素将是返回给调用方的值(在这种情况下,它将是数字100);元组的最后一个元素将是GenServer -current_number+1新状态,所以101
  5. 当您向此:next_number发送另一个call GenServer时,它将按照之前的步骤进行,除了内部状态现在为101,并且从函数,新状态将为102,依此类推...

答案 1 :(得分:1)

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)时,它会以新状态被调用,然后返回新状态,依此类推...