llo, "world"}
:ok
iex> flush
:ok
也可以通过 receive/1 函数来接收
iex> send self(), {:hello, "world"}
{:hello, "world"}
iex> receive do
...> {:hi, msg} -> msg
...> {:hello, msg} -> msg
...> end
"world"
receive/1 函数收不到消息会阻塞,可以给它设置一个超时时间
iex> receive do
...> {:hello, msg} -> msg
...> after
...> 3000 -> "timeout"
...> end
"timeout"
进程间的连接 进程B连接进程A之后,进程A出现异常,进程B就能捕获,这样进程B就能处理进程A的异常 进程连接的方式很简单,就是 spawn_link/1 函数
iex> spawn fn -> raise "oops" end
#PID<0.76.0>
15: 18:22.804 [error] Process #PID<0.76.0> raised an exception
** (RuntimeError) oops
:erlang.apply/2
iex> spawn_link fn -> raise "oops" end
** (EXIT from #PID<0.73.0>) an exception was raised:
** (RuntimeError) oops
:erlang.apply/2
15: 18:31.533 [error] Process #PID<0.78.0> raised an exception
** (RuntimeError) oops
:erlang.apply/2
关注 Process模块 模块,里面提供了进程操作的函数
进程中保存状态的方法:
defmodule KV do
def start do
{:ok, spawn_link(fn -> loop(%{}) end)}
end
defp loop(map) do
receive do
{:get, key, caller} ->
send caller, Map.get(map, key)
loop(map)
{:put, key, value} ->
loop(Map.put(map, key, value))
end
end
end
iex> send pid, {:put, :hello, :world}
#PID<0.62.0>
iex> send pid, {:get, :hello, self()}
{:get, :hello, #PID<0.41.0>}
iex> flush
:world
实际使用时,可以用 Agent 模块 来简化上面的操作。
模块属性
elixir中模块的属性主要有3个作用:
- 作为一个模块的注释,通常附加上用户或虚拟机用到的信息
- 作为常量
- 在编译时作为一个临时的模块存储
注释
注释时,一些常用的模块属性如下:
名称 |
含义 |
@moduledoc |
为当前模块提供文档 |
@doc |
为该属性后面的函数或宏提供文档 |
@behaviour |
(注意这个单词是英式拼法)用来注明一个OTP或用户自定义行为 |
@before\_compile |
提供一个每当模块被编译之前执行的钩子。这使得我们可以在模块被编译之前往里面注入函数。 |
常量
作为常量:
defmodule MyServer do
@my_data 14
def first_data, do: @my_data
@my_data 13
def second_data, do: @my_data
end
测试方法:
iex> MyServer.first_data
14
iex> MyServer.second_data
13
临时存储
模块中的变量只在编译时存在,所以用做临时存储,存储一些只在编译时使用的变量。 示例:
defmodule MyServer do
@my_data 14
def first_data, do: @my_data
@my_data 13
def second_data, do: @my_data
end
iex> MyServer.first_data #=> 14
iex> MyServer.second_data #=> 13
结构体
定义
defmodule User do
defstruct name: "harry", age: 32
end
使用方式
iex> j = %User{}
%User{age: 32, name: "harry"}
iex> j.name
"harry"
iex> j[:name]
** (UndefinedFunctionError) undefined function User.fetch/2
User.fetch(%User{age: 32, name: "harry"}, :name)
(elixir) lib/access.ex:77: Access.get/3
iex> j.__struct__
User
协议
协议类似于其他语言中的接口,谁实现了协议,谁就可以使用协议, 比如下面的例子,Integer 和 User 结构体实现了协议,就可以使用协议中的方法。
defmodule User do
defstruct name: "harry", age: 32
end
defprotocol Enough do
def enough?(data)
end
defimpl Enough, for: Integer do
def enough?(data) do
if data > 0 do
true
else
false
end
end
end
defimpl Enough, for: User do
def enough?(data) do
if data.age > 18 do
true
else
false
end
end
end
使用示例:
iex> Enough.enough?(11)
true
iex> Enough.enough?(0)
false
iex> u = %User{}
%User{age: 32, name: "harry"}
iex> Enough.enough?(u)
true
iex> u = %{u|age: 10}
%User{age: 10, name: "harry"}
iex> Enough.enough?(u)
false
iex> Enough.enough?("string")
** (Protocol.UndefinedErro
|