채널 닫기: close
채널 닫기: close
Go에는 채널을 '더 이상 값을 보내지 않겠다'고 알려주는 내장 함수 close가 있어요. 채널을 사용하다 보면 "값 전송이 끝났다는 걸 상대방에게 어떻게 알리지?" 하는 순간이 오는데요, 그때 바로 이 함수를 쓰게 됩니다. 오늘은 close의 동작 방식과, 닫힌 채널에서 값을 받을 때 생기는 일을 차근차근 살펴볼게요.
출처: Go Specification
본문
채널 ch에 대해 내장 함수 close(ch)는 이 채널로 더 이상 값을 보내지 않겠다는 사실을 기록해요. 즉, 닫기 호출 시점부터 그 채널을 통한 전송이 끝났음을 언어가 알고 있는 거죠.
주의할 점이 몇 가지 있어요. 우선 ch가 수신 전용(receive-only) 채널이면 오류(error)예요. 닫는 동작은 보내는 측의 책임이니까, 받기만 하는 채널을 닫으려는 건 말이 안 되는 거죠.
그리고 이미 닫힌 채널에 값을 보내거나, 닫힌 채널을 다시 닫는 것도 문제인데요, 이 경우 런타임 패닉(run-time panic)이 발생해요. nil 채널을 닫는 것도 마찬가지로 패닉을 일으켜요.
close를 호출한 뒤, 그리고 이전에 보냈던 값들을 모두 수신한 뒤에는, 수신 연산이 블로킹되지 않고 채널 타입의 zero value를 반환해요. 여기서 중요한 건 값이 아니라 "이제 채널이 닫혔구나"라는 사실을 수신 측이 알 수 있다는 점이에요.
한 가지 더 — 다중 값(multi-valued) 수신 연산은 받은 값과 함께 채널이 닫혔는지 여부를 나타내는 지표도 함께 반환해요. 그래서 수신 측에서는 이 두 번째 반환값으로 "값이 끝났다"를 판단할 수 있죠. 실제로 채널을 순회하면서 값을 소비하는 for range 같은 패턴이 닫힘 판정에 기반해 동작하는 이유이기도 해요.
마지막으로, close의 인자 타입이 type parameter라면 조금 더 신경 써야 해요. 그 type parameter의 type set에 있는 모든 타입이 채널이어야 하고, 그중 어느 하나라도 수신 전용 채널이면 역시 오류예요.
더 알아보기
- Receive operator: 수신 연산 — 채널에서 값을 받는 문법과 다중 값 수신
- Run-time panics: 런타임 패닉 — 닫힌 채널 사용 시 어떤 패닉이 일어나는지
- Type parameter declarations: 타입 파라미터 — 제네릭 채널에서
close를 쓸 때의 제약