채널과 코루틴
채널과 코루틴
섹션 제목: “채널과 코루틴”코루틴 간 통신을 위한 Go 스타일 채널. 버퍼드 또는 언버퍼드 채널을 생성하고, 값을 보내고 받고, select 문을 사용하여 동시 프로세스 간에 조율합니다.
channel 전역은 항상 사용 가능합니다.
채널 생성
섹션 제목: “채널 생성”언버퍼드 채널(크기 0)은 전송이 완료되기 전에 송신자와 수신자 모두 준비되어야 합니다. 버퍼드 채널은 공간이 있는 동안 즉시 전송을 완료할 수 있습니다:
-- 언버퍼드: 송신자와 수신자 동기화local sync_ch = channel.new()
-- 버퍼드: 최대 10개 메시지 큐local work_queue = channel.new(10)| 파라미터 | 타입 | 설명 |
|---|---|---|
size | integer | 버퍼 용량 (기본값: 0, 언버퍼드) |
반환: channel
값 보내기
섹션 제목: “값 보내기”채널에 값을 보냅니다. 수신자가 준비될 때까지(언버퍼드) 또는 버퍼 공간이 있을 때까지(버퍼드) 블록합니다:
-- 워커 풀에 작업 전송local jobs = channel.new(100)for i, task in ipairs(tasks) do jobs:send(task) -- 버퍼가 가득 차면 블록endjobs:close() -- 더 이상 작업 없음 신호| 파라미터 | 타입 | 설명 |
|---|---|---|
value | any | 보낼 값 |
반환: boolean
채널이 닫혀 있으면 에러 발생.
값 받기
섹션 제목: “값 받기”채널에서 값을 받습니다. 값이 있거나 채널이 닫힐 때까지 블록합니다:
-- 작업 큐에서 소비하는 워커while true do local job, ok = work:receive() if not ok then break -- 채널 닫힘, 더 이상 작업 없음 end process(job)end반환: any, boolean
value, true- 값을 받음nil, false- 채널 닫히고 비어있음
채널 닫기
섹션 제목: “채널 닫기”채널을 닫습니다. 대기 중인 송신자는 에러를 받고, 대기 중인 수신자는 nil, false를 받습니다. 이미 닫혀 있으면 에러 발생:
local results = channel.new(10)
-- 생산자가 결과 채움for _, item in ipairs(data) do results:send(process(item))endresults:close() -- 완료 신호여러 채널에서 Select
섹션 제목: “여러 채널에서 Select”여러 채널 작업을 동시에 대기합니다. 여러 이벤트 소스 처리, 타임아웃 구현, 반응형 시스템 구축에 필수적:
local result = channel.select(cases)| 파라미터 | 타입 | 설명 |
|---|---|---|
cases | table | select 케이스 배열 |
default | boolean | true이면 준비된 케이스가 없을 때 즉시 반환 |
반환: table - 필드: channel, value, ok, default
타임아웃 패턴
섹션 제목: “타임아웃 패턴”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.valueFan-in 패턴
섹션 제목: “Fan-in 패턴”여러 소스를 하나의 핸들러로 병합.
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) endend논블로킹 확인
섹션 제목: “논블로킹 확인”블로킹 없이 데이터가 있는지 확인.
local r = channel.select { ch:case_receive(), default = true}
if r.default then -- 사용 가능한 것 없음, 다른 것 수행else process(r.value)endSelect 케이스 생성
섹션 제목: “Select 케이스 생성”channel.select와 함께 사용할 케이스 생성:
-- Send 케이스 - 채널이 값을 받을 수 있을 때 완료ch:case_send(value)
-- Receive 케이스 - 값이 있을 때 완료ch:case_receive()워커 풀 패턴
섹션 제목: “워커 풀 패턴”local work = channel.new(100)local results = channel.new(100)
-- 워커 스폰for i = 1, num_workers do process.spawn("app.workers:processor", "app:processes", work, results)end
-- 작업 공급for _, item in ipairs(items) do work:send(item)endwork:close()
-- 결과 수집local processed = {}while #processed < #items do local result, ok = results:receive() if not ok then break end table.insert(processed, result)end| 조건 | 종류 | 재시도 가능 |
|---|---|---|
| 닫힌 채널에 Send | 런타임 에러 | 아니오 |
| 닫힌 채널 Close | 런타임 에러 | 아니오 |
| select에서 잘못된 케이스 | 런타임 에러 | 아니오 |