【问题标题】:Elixir understanding GenServerElixir 理解 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 参数

【问题讨论】:

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


【解决方案1】:

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

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

考虑场景:

  1. 您正在使用编号 100 初始化 GenServer
  2. 您向此GenServer - :next_number 发送消息(更具体的call)。
  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. 当你向这个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)时,它会以新状态调用,然后你返回新状态,以此类推...

    【讨论】:

      猜你喜欢
      • 2017-10-16
      • 1970-01-01
      • 2021-03-03
      • 2016-03-14
      • 2017-02-17
      • 2018-01-13
      • 1970-01-01
      • 1970-01-01
      • 2015-01-17
      相关资源
      最近更新 更多