iT邦幫忙

2024 iThome 鐵人賽

DAY 9
0

我們在使用 spawn 或是他的延伸 Agent,雖然很靈活,但還是有什麼都要自己來的感覺。這時候就可以使用 OTP 裡面最常用的 GenServer。

可以把它當成是底層的框架,替我們寫好了所有需要的功能,以及統一的狀態管理與接收訊息機制,最棒的是這套機制從 Erlang 開始到現在,已經是千錘百鍊的狀態,用起來額外安心。

GenServer behaviour

ㄧ樣拿先前的簡單銀行帳戶為範例,我們可以在 module 裡面加上 use GenServer 來使用這個 behaviour

defmodule Bank do
  use GenServer
end

就這樣直接執行的時候會跳出這個警告

warning: function init/1 required by behaviour GenServer is not implemented (in module Bank).

We will inject a default implementation for now:

    def init(init_arg) do
      {:ok, init_arg}
    end

You can copy the implementation above or define your own that converts the arguments given to GenServer.start_link/3 to the server state.

└─ iex:1: Bank (module)

GenServer 有一系列的 callback 函式需要我們定義,首先最不能少的就是起始的狀態

defmodule Bank do
  use GenServer
  
  def init(init_balance) do
    IO.puts "開戶存了 #{init_balance} 元。"
    {:ok, init_balance}
  end
end

GenServer 規定每個 callback 回覆的格式,在 init/1 這個 callback,我們要回傳的是由 :ok 與 GenServer 起始的狀態(以例子來說,是帳戶的初始值)所組成的 tuple:{:ok, init_balance}

啟動

使用 GenServer.start_link/3 來啟動我們定義好的 GenServer

{:ok, pid} = GenServer.start_link(Bank, 3000)

執行結果

iex(3)> {:ok, pid} = GenServer.start_link(Bank, 3000)
開戶存了 3000 元。
{:ok, #PID<0.129.0>}

下一篇我們會接收訊息,並改變狀態


上一篇
08 Task
下一篇
10 GenServer 訊息
系列文
Elixir 多工 : Processes 與 OTP30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言