HelloWorld 与 Elixir 使用教程
Elixir 是基于 BEAM(Erlang 虚拟机)的函数式并发语言,写 HelloWorld 最直接的两种方式是:在交互式 shell(iex)里即时输出,或创建模块/脚本用 mix/elixirc 编译运行。理解模块、函数、进程与 Mix 工具链,能让你从简单示例自然过渡到并发、测试与发布流程。

Table of Contents
Toggle我先把思路讲清楚:为什么学 HelloWorld 要关心这些
费曼法告诉我们:把复杂的东西拆成简单的块再解释。写一个 HelloWorld 看似很简单,但对于 Elixir 来说,关键不在于那句输出语,而在于运行它的环境和工具链——iex(交互式)、脚本、模块、Mix 项目、编译与发布。理解这些,你就能把后续的并发、OTP、测试和部署都串起来。
准备工作:安装与验证
不啰嗦,先确保环境对了。常见做法是通过官方包管理器安装 Erlang,然后安装 Elixir,或者用 asdf 管理版本。安装后,你可以这样快速验证:
- 验证 Erlang/Elixir:在终端运行 erl 或 elixir –version、iex –version。
- 打开交互式 shell:运行 iex,你就可以即时执行 Elixir 表达式。
常用命令一览(表格)
| 命令 | 用途 |
| elixir file.exs | 直接运行脚本(不编译到 .beam) |
| elixirc file.ex | 编译 .ex 源文件生成 .beam(Erlang VM 格式) |
| iex | 交互式 shell,适合试验和调试 |
| mix new my_app | 创建 Mix 项目骨架 |
| mix test | 运行测试 |
| mix release | 构建发行包(部署用) |
HelloWorld:从最简单到项目化的步骤
1) 在 iex 里即时输出(最快)
打开终端,输入 iex,它会给你一个提示符。然后直接键入:
iex> IO.puts("Hello, world!")
结果会立即打印。这个方式像是在试验台上直接点燃火花,适合验证表达式或库函数。
2) 用脚本文件(.exs)运行
把内容写到一个文件,比如 hello.exs:
IO.puts("Hello, world from script!")
运行:elixir hello.exs。这种方式适合小工具、一次性脚本或学习流程。
3) 用模块和函数(更接近真实工程)
当你需要写可重用代码时,应该把逻辑包在模块中。创建 hello.ex:
defmodule Hello do
def world do
IO.puts("Hello, world from module!")
end
end
编译并在 iex 中加载:
elixirc hello.ex
iex -S mix
# 或在 iex 中: c("hello.ex"); Hello.world()
注意:elixirc 会生成 .beam 文件,可以被 Erlang VM 直接加载。
4) 使用 Mix 创建项目并运行
真实项目通常使用 Mix 管理。命令:
mix new demo
cd demo
# 在 lib/demo.ex 写模块,或在 lib/demo/application.ex 配置应用
在项目里,你可以运行 mix run -e ‘Demo.hello()’ 来执行指定函数,或者 iex -S mix 进入带项目依赖的交互式环境。
深入一点:Elixir 的核心概念(用最简单的话解释)
把 Elixir 想象成一套工具箱,工具箱里有模块、函数、进程、消息、以及一把叫 BEAM 的坚固发动机。你写模块和函数来描述计算,把并发问题交给进程和消息来解决,Mix 帮你组织和发布。下面逐个拆开说。
模块与函数
- 模块(Module):就是命名空间,把函数组织起来。用 defmodule 定义。
- 函数(Function):通过 def 定义,可以有不同的参数模式(重载式)和守卫。
示例(带参数匹配):
defmodule Greeter do
def hello("world"), do: IO.puts("Hello, world!")
def hello(name), do: IO.puts("Hello, " <> name)
end
模式匹配(pattern matching)和不可变性
模式匹配不是等号的替代品,而是解构数据、提取值的主要方式。变量一旦绑定,在同一作用域内不可变——这让并发更安全,更容易推理。
{a, b} = {1, 2}
# a = 1, b = 2
进程与消息(并发基础)
Elixir 的“轻量级进程”非常便宜,可以成千上万地并发运行。进程通过消息传递通信,没有共享内存,从而避免很多并发陷阱。
spawn(fn -> IO.puts("I am a process") end)
更实用的是用 GenServer 去封装状态和行为,这属于 OTP 的范畴。
把 HelloWorld 做成一个小服务(举例)
好,我们来做个小 demo:用 GenServer 管理一个简单的问候计数器,每次调用都会返回问候消息并增加计数。这样可以把“HelloWorld”从一句输出变成一个带状态的服务。
代码示例(简洁版 GenServer)
defmodule HelloCounter do
use GenServer
# Client API
def start_link(initial \\ 0), do: GenServer.start_link(__MODULE__, initial, name: __MODULE__)
def greet(), do: GenServer.call(__MODULE__, :greet)
# Server callbacks
def init(count), do: {:ok, count}
def handle_call(:greet, _from, count) do
msg = "Hello! You've been greeted #{count} times."
{:reply, msg, count + 1}
end
end
# 启动与调用(在 iex -S mix 中)
{:ok, _} = HelloCounter.start_link(1)
HelloCounter.greet()
看,这比简单打印丰富得多:有状态、可测试、可扩展。
测试、工具与调试
写完代码别忘了测试。Elixir 默认集成 ExUnit。简单示例:
defmodule HelloTest do
use ExUnit.Case
test "greet increments" do
{:ok, _} = HelloCounter.start_link(0)
assert HelloCounter.greet() =~ "greeted 0"
assert HelloCounter.greet() =~ "greeted 1"
end
end
调试时常用:
- iex.pry / IEx.pry():可以在运行时进入调试交互式会话(需要在 mix.exs 启用 :debug 或使用 require IEx)。
- Logger:Elixir 的日志工具,支持不同等级和后端。
部署与发布(简单说明)
生产部署通常用 Mix Releases(自带)或者 Distillery(较老),思路是生成一个包含 Erlang VM、应用和依赖的可运行包。基本流程:
- 在 mix.exs 中配置 release。
- 运行 mix release 生成可部署目录。
- 在目标机器上解压并使用生成的脚本来启动/停止。
这就是为什么早期我们强调理解 Mix:它把创建、测试、打包、发布串成一条流水线。
性能与常见陷阱(实用提醒)
- 不要把 CPU 密集型任务放到 BEAM 进程里:BEAM 擅长并发 I/O 与大量轻量任务,但密集计算会阻塞调度器,应该用 NIF、C 驱动或独立服务。
- 避免全局可变状态:借助 Agent/GenServer 管理状态,而不是用全局可变结构。
- 监控和观察:在生产环境开启 telemetry、Prometheus 导出或其他 APM,以便发现瓶颈。
- 理解 supervision tree:用监督树管理进程生命周期,使系统有自愈能力。
小贴士:把学习路径拆成小步
- 第一周:熟悉 iex、基本语法、模块与函数、pattern matching。
- 第二周:学 Mix,写小项目,增加测试(ExUnit)。
- 第三周:探索并发(spawn、Tasks、GenServer),实现一个小服务。
- 第四周:学习 supervision、release,尝试打包并在另一台机器上运行。
按这样的节奏,你会发现从一句 HelloWorld 到能上线的服务,路径并不长,关键是每一步都弄懂“为什么”。
常见问题快速解答
- Q:什么时候用 .exs 与 .ex?
A:脚本(.exs)适合一次性任务或快速试验;模块与库用 .ex(可编译成 .beam),用于生产与测试。
- Q:如何在项目里使用第三方依赖?
A:在 mix.exs 的 deps 函数里声明依赖,然后 run mix deps.get。
- Q:如何优雅地终止 GenServer?
A:使用 GenServer.stop/3 或让 supervisor 管理其重启策略。
参考与继续学习的方向(简单列举)
- Elixir 官方文档与 Getting Started;
- 《Programming Elixir》以及 José Valim 的讲座/文章;
- 学习 OTP 原理(GenServer、Supervisor、Application);
- 实践:把一个小服务从本地部署到远端,观察日志与性能。
行文到这里,我自己也有点想再跑一个例子来确认行为,嗯……不过基本思路就是这样:先从 iex 和脚本感觉语言,再把功能包装到模块和 Mix 项目里,慢慢引入并发、测试与发布。一步一步来,别急着全部学完再动手,写第一个能跑的 HelloWorld,是最实在的开始。