Channels e Corrotinas
Channels e Corrotinas
Seção intitulada “Channels e Corrotinas”Channels estilo Go para comunicação entre corrotinas. Crie channels com ou sem buffer, envie e receba valores, e coordene entre processos concorrentes usando instruções select.
O global channel está sempre disponível.
Criando Channels
Seção intitulada “Criando Channels”Channels sem buffer (tamanho 0) requerem que remetente e receptor estejam prontos antes da transferência completar. Channels com buffer permitem que envios completem imediatamente enquanto houver espaço disponível:
-- Sem buffer: sincroniza remetente e receptorlocal sync_ch = channel.new()
-- Com buffer: enfileirar até 10 mensagenslocal work_queue = channel.new(10)| Parâmetro | Tipo | Descrição |
|---|---|---|
size | integer | Capacidade do buffer (padrão: 0 para sem buffer) |
Retorna: channel
Enviando Valores
Seção intitulada “Enviando Valores”Enviar um valor para o channel. Bloqueia até um receptor estar pronto (sem buffer) ou espaço no buffer estar disponível (com buffer):
-- Enviar trabalho para pool de workerslocal jobs = channel.new(100)for i, task in ipairs(tasks) do jobs:send(task) -- Bloqueia se buffer cheioendjobs:close() -- Sinalizar que não há mais trabalho| Parâmetro | Tipo | Descrição |
|---|---|---|
value | any | Valor a enviar |
Retorna: boolean
Lança erro se channel estiver fechado.
Recebendo Valores
Seção intitulada “Recebendo Valores”Receber um valor do channel. Bloqueia até um valor estar disponível ou o channel estar fechado:
-- Worker consumindo da fila de jobswhile true do local job, ok = work:receive() if not ok then break -- Channel fechado, não há mais trabalho end process(job)endRetorna: any, boolean
value, true- Recebeu um valornil, false- Channel fechado e vazio
Fechando Channels
Seção intitulada “Fechando Channels”Fechar o channel. Remetentes pendentes recebem erro, receptores pendentes recebem nil, false. Lança erro se já estiver fechado:
local results = channel.new(10)
-- Produtor preenche resultadosfor _, item in ipairs(data) do results:send(process(item))endresults:close() -- Sinalizar conclusãoSelecionando de Múltiplos Channels
Seção intitulada “Selecionando de Múltiplos Channels”Aguardar múltiplas operações de channel simultaneamente. Essencial para tratar múltiplas fontes de eventos, implementar timeouts e construir sistemas responsivos:
local result = channel.select(cases)| Parâmetro | Tipo | Descrição |
|---|---|---|
cases | table | Array de casos select |
default | boolean | Se true, retorna imediatamente quando nenhum caso está pronto |
Retorna: table com campos: channel, value, ok, default
Padrão de Timeout
Seção intitulada “Padrão de Timeout”Aguardar resultado com timeout usando time.after().
local time = require("time")
local result_ch = worker:response()local timeout = time.after("5s")
local r = channel.select { result_ch:case_receive(), timeout:case_receive()}
if r.channel == timeout then return nil, errors.new("TIMEOUT", "Operation timed out")endreturn r.valuePadrão Fan-in
Seção intitulada “Padrão Fan-in”Mesclar múltiplas fontes em um handler.
local events = process.events()local inbox = process.inbox()local shutdown = channel.new()
while true do local r = channel.select { events:case_receive(), inbox:case_receive(), shutdown:case_receive() }
if r.channel == shutdown then break elseif r.channel == events then handle_event(r.value) else handle_message(r.value) endendVerificação Não-Bloqueante
Seção intitulada “Verificação Não-Bloqueante”Verificar se dados estão disponíveis sem bloquear.
local r = channel.select { ch:case_receive(), default = true}
if r.default then -- Nada disponível, fazer outra coisaelse process(r.value)endCriando Casos Select
Seção intitulada “Criando Casos Select”Criar casos para uso com channel.select:
-- Caso send - completa quando channel pode aceitar valorch:case_send(value)
-- Caso receive - completa quando valor disponívelch:case_receive()Padrão Worker Pool
Seção intitulada “Padrão Worker Pool”local work = channel.new(100)local results = channel.new(100)
-- Criar workersfor i = 1, num_workers do process.spawn("app.workers:processor", "app:processes", work, results)end
-- Alimentar trabalhofor _, item in ipairs(items) do work:send(item)endwork:close()
-- Coletar resultadoslocal processed = {}while #processed < #items do local result, ok = results:receive() if not ok then break end table.insert(processed, result)end| Condição | Tipo | Retentável |
|---|---|---|
| Send em channel fechado | erro runtime | não |
| Close de channel fechado | erro runtime | não |
| Caso inválido em select | erro runtime | não |
Veja Também
Seção intitulada “Veja Também”- Process Management - Criação e comunicação de processos
- Message Queue - Mensagens baseadas em fila
- Functions - Invocação de funções