Полное руководство по Erlang: от основ синтаксиса до конкурентной модели с примерами кода

Исчерпывающее введение в язык Erlang и платформу OTP: от базового синтаксиса, сопоставления с образцом и структур данных до легковесных процессов, обмена сообщениями, супервизоров и примеров кода для gen_server.
Erlang — это не просто язык программирования. Это целая экосистема, созданная компанией Ericsson для разработки отказоустойчивых, распределенных, параллельных систем с высокой доступностью, где время простоя измеряется минутами в год. Если ваша задача — создание высоконагруженных backend-систем, мессенджеров, игровых серверов или систем телекома, понимание Erlang открывает путь к архитектурам, устойчивым к сбоям по замыслу.

Фундамент Erlang — это функциональный язык с динамической типизацией и строгой оценкой (eager evaluation). Начнем с базовых строительных блоков. Все данные в Erlang — это термы (terms). Простые типы включают числа (целые и числа с плавающей точкой, причем целые имеют неограниченную точность), атомы (atom) — константы, чье имя является их значением (например, ok, error, my_atom), и бинарные данные (binaries) для эффективной работы с битовыми последовательностями.

Списки (lists) и кортежи (tuples) — ключевые структуры данных. Список — это последовательность элементов, заключенная в квадратные скобки. Он часто строится с использованием головы (head) и хвоста (tail).
Пример:
List = [1, 2, 3, 4].
[Head | Tail] = List. % Head = 1, Tail = [2,3,4]
Кортеж — это фиксированное количество элементов, заключенных в фигурные скобки. Он часто используется для группировки связанных данных.
Пример:
Point = {point, 10, 20}.
{point, X, Y} = Point. % X = 10, Y = 20

Сопоставление с образцом (pattern matching) — это краеугольный камень Erlang, а не просто присваивание. Оператор `=` выполняет сопоставление, пытаясь сделать левую часть равной правой.
Пример:
{A, B} = {10, 20}. % Успех: A=10, B=20
{A, 20} = {30, 20}. % Успех: A=30
{A, B} = {1, 2, 3}. % Ошибка! Несоответствие паттернов

Функции определяются в модулях (modules). Модуль — это базовая единица кода. Одна функция может иметь несколько клауз (clauses), которые выбираются через сопоставление с образцом аргументов.
Пример модуля geometry.erl:
-module(geometry).
-export([area/1]).

area({rectangle, Width, Height}) -> Width * Height;
area({circle, Radius}) -> 3.14159 * Radius * Radius.
Компиляция: c(geometry). Вызов: geometry:area({rectangle, 10, 5}). % Вернет 50

Но истинная сила Erlang раскрывается в его конкурентной модели. Легковесные процессы (processes) — это изолированные единицы выполнения, не являющиеся потоками ОС. Их можно создавать десятки и даже сотни тысяч. Процессы общаются только через асинхронную передачу сообщений (message passing). Каждый процесс имеет свой почтовый ящик (mailbox).
Пример создания процесса и обмена сообщениями:
Pid = spawn(fun() -> receiver() end). % Создание процесса
Pid ! {self(), hello}. % Отправка сообщения {PID_отправителя, hello}

receiver() ->
 receive
 {From, Message} ->
 io:format("Received ~p from ~p~n", [Message, From]);
 Other ->
 io:format("Unexpected: ~p~n", [Other])
 end.

Управление ошибками в Erlang реализовано по философии «пусть он упадет» (let it crash). Вместо написания оборонительного кода, переполненного проверками, вы создаете деревья процессов-супервизоров (supervisors), которые следят за рабочими процессами (workers). Если рабочий процесс падает из-за непредвиденной ошибки, супервизор автоматически перезапускает его по заданной стратегии (например, один за одним, все вместе). Это позволяет изолировать сбои и создавать системы, которые самовосстанавливаются.
Пример простого супервизора:
-module(my_supervisor).
-behaviour(supervisor).

init([]) ->
 SupFlags = #{strategy => one_for_one, intensity => 5, period => 10},
 ChildSpec = #{
 id => worker_id,
 start => {my_worker, start_link, []},
 restart => permanent,
 shutdown => 2000
 },
 {ok, {SupFlags, [ChildSpec]}}.

Библиотека OTP (Open Telecom Platform) — это набор библиотек и паттернов, которые формализуют лучшие практики для создания устойчивых приложений. Ключевые поведения (behaviours): gen_server (универсальный сервер клиент-сервер), gen_statem (конечный автомат), supervisor (супервизор). Использование OTP избавляет от написания шаблонного кода и обеспечивает стандартизацию.
Пример простого gen_server:
-module(key_value_store).
-behaviour(gen_server).

% Клиентские функции
start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
put(Key, Value) -> gen_server:call(?MODULE, {put, Key, Value}).
get(Key) -> gen_server:call(?MODULE, {get, Key}).

% Колбэки сервера
init([]) -> {ok, #{}}.

handle_call({put, Key, Value}, _From, State) ->
 NewState = maps:put(Key, Value, State),
 {reply, ok, NewState};
handle_call({get, Key}, _From, State) ->
 Reply = maps:get(Key, State, not_found),
 {reply, Reply, State}.

Работа с бинарными данными и битовыми строками (bitstrings) в Erlang невероятно мощна и синтаксически элегантна, что идеально подходит для парсинга сетевых протоколов.
Пример:
= Data.
Этот один оператор извлекает 8-битный заголовок, 16-битную длину полезной нагрузки (в little-endian), затем саму полезную нагрузку указанной длины как бинарник, и остаток данных.

Изучение Erlang — это инвестиция в парадигму построения систем, где параллелизм, распределенность и отказоустойчивость являются не проблемами, а встроенными возможностями. Начните с основ синтаксиса и сопоставления с образцом, затем погрузитесь в модель процессов и обмен сообщениями, и, наконец, освойте мощь OTP. Это позволит вам создавать системы, которые не просто работают, а остаются в строю при любых обстоятельствах.
216 3

Комментарии (8)

avatar
l2ujmxgh9koj 27.03.2026
Спасибо за структурированный материал. Теперь понятно, почему WhatsApp выбрал именно Erlang.
avatar
sogk01i4 28.03.2026
Жаль, что не затронули OTP-библиотеки. Без них руководство не совсем 'полное', как в заголовке.
avatar
0z7u96i 28.03.2026
Сложновато для новичка. Не хватает более простых примеров в начале статьи.
avatar
nb1vr5utp7 29.03.2026
Работаю с Erlang 5 лет. В статье хорошо раскрыта его философия — отказоустойчивость прежде всего.
avatar
vig8l2 29.03.2026
Отличное руководство! Как раз искал материал по конкурентной модели Erlang для своего проекта.
avatar
emrd97hfy7y 29.03.2026
Для тех, кто только начинает, рекомендую сначала изучить базовый функциональный подход.
avatar
rb3c3iqulhw 30.03.2026
Очень вовремя! Интересно, насколько Erlang актуален для современных микросервисов?
avatar
6m8ra9l5 30.03.2026
Примеры кода — то, что нужно! Сразу видно мощь pattern matching и легковесных процессов.
Вы просмотрели все комментарии