🔥 채널 닫기와 range 문

282자
4분

채널을 닫는 것은 더 이상 값을 보내지 않겠다는 것을 나타내는 중요한 방법이에요. 채널이 닫혔는지 확인하려면 두 번째 반환값을 사용합니다.

v, ok := <-ch
 
go

위의 코드에서 ok는 채널 ch에서 더 이상 받을 값이 없고 채널이 닫혔을 때 false가 됩니다.

for i := range c 루프는 채널 c가 닫힐 때까지 계속해서 값을 받아요.

주의할 점은 채널을 닫는 것은 보내는 쪽에서만 해야 한다는 거예요. 받는 쪽에서는 절대로 채널을 닫으면 안 돼요. 닫힌 채널로 값을 보내면 패닉이 발생합니다!

또 주의할 점은 채널은 파일과 다르게 보통 닫을 필요가 없어요. range 루프를 종료하는 것처럼 더 이상 값이 오지 않는다는 것을 알려줘야 할 때만 채널을 닫으면 됩니다.

아래는 채널을 닫는 예제 코드예요.

package main
 
import (
	"fmt"
)
 
func fibonacci(n int, c chan int) {
	x, y := 0, 1
	for i := 0; i < n; i++ {
		c <- x  // 채널에 피보나치 수를 보냄
		x, y = y, x+y  // 다음 피보나치 수를 계산함
	}
	close(c)  // 모든 피보나치 수를 보냈으므로 채널을 닫음
}
 
func main() {
	c := make(chan int, 10)  // 버퍼 크기가 10인 정수형 채널을 생성함
	go fibonacci(cap(c), c)  // 고루틴에서 피보나치 수를 채널에 보냄
	for i := range c {  // 채널이 닫힐 때까지 계속 값을 받음
		fmt.Println(i)  // 받은 피보나치 수를 출력함
	}
}
 
go

위의 예제 코드를 보면 fibonacci 함수에서 채널 c에 피보나치 수를 차례대로 보내다가 모든 값을 다 보내면 close(c)로 채널을 닫아요.

그러면 main 함수에서 for i := range c 루프로 채널 c에서 값을 계속 받다가 채널이 닫히면 루프가 자동으로 종료되는 거죠. 채널을 닫지 않으면 계속 값을 기다리다 데드락에 걸릴 수 있어요.

이처럼 채널을 적절히 닫아 주는 것이 중요해요. 하지만 꼭 필요할 때만 닫아야 해요. 필요 없는데 닫으면 오히려 버그의 원인이 될 수 있거든요.