알고나면 스트레스가 줄어드는 golang channel (with select)
[golang] 채널이란?
[이더리움에서 배우는 Go언어] chan chan 이란?
ChatGPT
Go에서 Channel이 자주 헷갈려서 정리해보고자 한다.
Channel은 고루틴 간의 통신을 위해 사용되는 중요한 동시성 도구이다.
1. 채널 생성과 타입
ch := make(chan int)
- 채널은 특정 타입의 데이터를 송수신하는 데 사용되며,
make 함수를 통해 생성한다.
- 채널 타입은 송수신할 데이터의 타입과 동일해야 한다.
2. 채널 송수신
- 송신 Send: 데이터를 채널에 송신할 때는
ch <- data 구문을 사용
- 수신 Receive: 데이터를 수신할 때는
data := <- ch 구문을 사용
- 채널에 데이터를 송신할 때는 반드시 수신 준비가 되어 있어야 한다.
- 준비가 되어 있지 않으면, 해당 고루틴은 블로킹(blocking)된다. 이로 인해 데드락(deadlock)이 발생할 수 있다.
3. 버퍼드(Buffered) 채널
ch := make(chan int, 3)
- 채널에 버퍼를 설정하여, 일정 수의 메시지를 보관할 수 있다.
- 버퍼가 꽉 차면 송신은 블로킹되며, 버퍼가 비어있으면 수신은 블로킹된다.
- 버퍼드 채널을 활용하면 송수신이 준비되지 않은 상황에서 데이터가 잠시 보관될 수 있어 유용하다.
4. 언버퍼드(UnBuffered) 채널
- 기본적으로 Go의 채널은 언버퍼드이다.
- 즉, 송신과 수신이 동시에 이루어져야 한다.
- 두 고루틴이 동시에 send와 receive에 응답하지 않으면, 블로킹된다.
5. 채널 닫기
close(ch)
close 함수를 사용해 채널을 닫을 수 있다.
- 닫힌 채널에 데이터를 송신하려 하면 패닉(panic)이 발생한다.
v, ok := <-ch
- 수신할 때는 채널이 닫혔는지 여부를 확인할 수 있다.
6. 채널의 방향 제한
func sendOnly(ch chan <- int, val int) {ch <- val}
func receiveOnly(ch <- chan int) int {return <- ch}
- 특정 함수에서 채널을 송신 전용(
chan <- T) 또는 수신 전용(<-- chan T)으로 제한할 수 있다.
- 방향이 제한된 채널은 해당 방향으로만 사용 가능해, 의도하지 않은 송수신을 방지할 수 있다.
7. select 구문
select {
case msg := <-ch1:
fmt.Println("Received from ch1:", msg)
case msg := <-ch2:
fmt.Println("Received from ch2:", msg)
default:
fmt.Println("No channel is ready")
}
select 구문을 사용하여 여러 채널의 송수신을 동시에 기다릴 수 있다.
- 각 케이스는 채널의 준비 상태에 따라 실행되며, 채널의 블로킹을 해결하는 데 유용하다.
default는 모든 채널이 블로킹 상태일 때 실행된다.
8. 데드락(Deadlock) 주의
- 채널에서 수신할 준비가 되어 있지 않은 상태에서 데이터를 송신하면 데드락이 발생한다.
- 특히 언버퍼드 채널에서, 단일 고루틴에서 송신과 수신을 모두 처리하려고 하면 데드락이 발생할 수 있으니 주의해야 한다.
9. 채널과 고루틴 종료 관리
- 채널을 통해 종료 신호를 전송하여 고루틴을 안전하게 종료할 수 있다.
- 예를 들어, quit 채널을 통해 종료를 알리고, 고루틴에서 이를 수신하여 종료하는 방식이다.
채널을 사용할 때 이러한 특징을 잘 이해하면, 효율적이고 안전하게 고루틴 간 통신을 관리할 수 있다.
10. 기타


