[Go] Channel - Range와 Close

윤동환·2023년 7월 4일
0

Go

목록 보기
6/18
post-thumbnail

close

전송자는 더이상 보낼 데이터가 없다는 것을 암시하기 위해 channel을 close할 수 있습니다. 수신자는 수신에 대한 표현에 두 번째 매개변수를 할당함으로써 채널이 닫혔는지 테스트 할 수 있습니다.

v, ok := <- ch

만약 더 수신할 값이 없고, channel이 닫혀있다면 ok의 값은 false입니다.

range

for i := range c

위의 반복문은 channel이 닫힐 때 까지 반복해서 channel에서 값을 수신합니다.

예제 1

channel이 닫혔는지 확인해보는 예제입니다.

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)
	go fibonacci(cap(c), c)
	b, ok := <- c
	fmt.Println(b, ok)
	for i := range c {
		fmt.Println(i)
	}
	v, ok := <- c
	fmt.Println(v, ok)
}

결과


for문에서range로 값을 빼기 전에는 true입니다. close되어 수신할 값이 없지만 아직 buffer는 채워져있기에 true가 나옵니다.
이때 b에 값을 하나 받았기 때문에 피보나치 수열의 0값이 함께 나옵니다.
마지막엔 뺄 값이 없기 때문에 0과 함께 false가 나옵니다.

절대로 수신자가 아닌 전송자만 channel을 닫아야합니다.
닫힌 channel에 전송한다면 panic을 야기할것입니다.

Channel은 파일과 다릅니다.
file과 달리 보통 channel을 닫을 필요는 없습니다.
channel을 닫는것은 range 반복문을종료시키는 것과 같이 수신자가 더이상 들어오는 값이 없다는 것을 알아야 하는 경우입니다.

예제 2

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)
	go fibonacci(cap(c), c)
	for i := range c {
		fmt.Print(i, " ")
	}
}

cap(c)의 값은 10입니다.

결과


위의 예제 코드처럼 fbonacci내에서 close를 해야합니다.(전송자)

수정 1

전송자의 close를 제거해보았습니다.

func fibonacci(n int, c chan int) {
	x, y := 0, 1
	for i := 0; i < n; i++ {
		c <- x
		x, y = y, x+y
	}
}

결과


range는 channel이 닫힐대 까지 값을 수신하는데 channel이 닫히지 않은상태에서 계속 받으려고 하기때문에 에러가 발생하였습니다.

수정 2

close를 전송자가 아닌 수신자에서 해보았습니다.

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
	}
}

func main() {
	c := make(chan int, 10)
	go fibonacci(cap(c), c)
	for i := range c {
		fmt.Println(i)
		close(c)
	}
}

결과


panic을 유발하였습니다.

수정 3

닫힌 channel에 send 해보았습니다.

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)
	go fibonacci(cap(c), c)
	for i := range c {
		c <- i
		fmt.Println(i)

	}
}

결과


마찬가지로 panic에 빠지며 closed된channel에 send했다고 혼냅니다.

만약 위의 코드에서close를 하지 않았다면 어떻게 될까요?

이처럼 channel에서 빼고 다시 넣기를 반복하며 무한루프에 빠지게 됩니다.

profile
모르면 공부하고 알게되면 공유하는 개발자

0개의 댓글