특정 고루틴을 종료시키기 위해(혹은 작업의 흐름을 취소시키기 위해) 채널을 만들어 쓸 때가 있다. 이때 이 채널을 어떻게 만드는지에 따라 일단 수준이 갈림
func slow(ch <-chan int, done <-chan bool) { ... for { select { case data := <-ch: ... case <-done: return } } } func main() { ... go slow(ch, done) ... done <- true ... }
상당히 많은 책에서 다루는 형태다. 그리고 잘 작동한다. 하지만 단순히 신호를 보내는 자체에만 의미가 있으며, 한번 보내고 나면 땡인 채널임에도 bool 자료형을 사용해 리소스를 낭비하는 형태다. 좋은 예제는 다음과 같이 빈 구조체 채널을 사용한다. 그리고 자료를 채널로 보내지 않고 닫아버린다!
func slow(ch <-chan int, done <-chan struct{}) { ... for { select { case data := <-ch: ... case <-done: return } } } func main() { ... go slow(ch, done) ... close(done) ... }
빈 구조체를 사용하기 때문에 신호가 가는 것 자체에 의의가 있다는 것에 합당하고, close 명령은 단순히 채널을 닫는 것이 아니라 브로드캐스팅 역할도 한다는 것을 이용한다는 것까지 활용했다. 예를 들어 slow 함수를 여러번 고루틴으로 실행시켰다면 앞의 예제였을 경우 true/false 값을 여러번 보내줘야 하나 close를 이용하면 한 방이다.
여기서 한 발 더 나아간 좋은 책은 이런 목적에 채널이 아닌 context를 사용한다. 다만 context는 1.7에서야 공식 라이브러리로 편입되었기 때문에 최신 책들에서 주로 소개된다..
댓글 0