더북(TheBook)

5.4.1 타임아웃

시간이 오래 걸리는 작업에 select 문을 이용하면 타임아웃 기능을 쉽게 구현할 수 있다.

다음 코드는 process() 작업에 타임아웃(10밀리초)을 적용한 코드이다.

done := process()
timeout := time.After(10 * time.Millisecond)
 
select {
case d := <-done:
    fmt.Println(d)
case <-timeout:
    fmt.Println("Time out!")
}

이 코드에서는 done 채널로 process() 함수의 실행 결과를 받아오고, timeout 채널로 10밀리초 후의 시간을 받아온다. select 문은 done 채널과 timeout 채널을 동시에 대기하다가 먼저 수신되는 케이스를 수행한다. 10밀리초 안에 process()의 작업이 완료되어 done 채널로 함수의 실행 결과가 수신되면 첫 번째 케이스를 수행하고, 10밀리초가 지나 timeout 채널로 값이 전달되면 “Time out!”을 출력하고 select 문은 종료된다. 즉, 이 코드는 process() 함수에 타임아웃 기능을 적용한 것이다.

이 코드에서 process() 함수는 타임아웃 처리 이후에도 계속해서 동작한다. 타임아웃 처리 이후에 process() 함수의 동작 상태를 제어하기 위한 방법으로 다음 세 가지를 생각해 볼 수 있다.

1. 아무 처리도 하지 않음

process() 작업이 이후 코드에 영향을 주지 않는다면 방금 본 코드처럼 타임아웃 후 process() 작업에 아무 처리도 안 해도 된다. 단, select 구문이 종료된 후에도 process() 함수는 계속 동작할 것이고, 처리가 완료된 후 done 채널로 전송된 값은 그냥 무시된다.

2. done 채널을 닫음

process() 함수에 타임아웃 처리가 되었다는 것을 알리기 위해 done 채널을 닫을 수 있다(close). 하지만 done 채널을 임의로 닫아버리면 process() 함수에서 처리를 완료한 후 done 채널에 처리 결과를 전송할 때 런타임 에러(panic: send on closed channel)가 발생한다. 타임아웃 처리로 done 채널을 닫을 때는 process() 함수에서 done 채널은 외부에서 닫힐 수 있다는 것을 고려해서 코드를 작성해야 한다.

3. process() 함수에 타임아웃 메시지를 전송

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.