728x90
반응형
Channel
- 채널은 고루틴 간의 데이터 파이프라인이다.
- 종류는 Unbuffered channel과 buffered channel로 구분된다.
- Unbuffered Channel: 동기적
- 수신 채널쪽에서 송신될 때 까지 채널이 묶는다. 즉 Block을 시키고 대기한다.
- 수신 채널이 준비되지 않다면 deadlock 에러가 발생한다.
- Buffered Channel: 비동기적
- 수신 채널이 데이터를 받을 준비가 되지 않더라도 지정된 버퍼만큼 데이터를 보내고 다음 작업을 수행한다.
- Unbuffered Channel: 동기적
- main() 함수는 가장 메인으로 생성되는 Goroutine이다.
채널 예시1
- 수신자는 goroutine으로부터 데이터가 채널을 통해 들어올 때 까지 대기한다.
func main() {
channel := make(chan int) // 정수 타입을 받는 채널 생성
go func() {
channel <- 123 // 채널에 123을 보냄
}()
var i int
// goroutine에서 데이터를 전송할 때까지 계속 대기
i = <- channel // 채널의 123을 수신한다.
}
채널 예시2
- 수신자와 송신자가 서로 기다리기 때문에, Goroutine 이 끝날 때 까지 기다리게 할 수 있음
func main() {
done := make(chan bool)
go func() {
for i := 0; i < 10; i +=1 {
fmt.Println(i)
}
done <- true
}()
<- done // 위 익명함수 Goroutine이 종료될 때까지 대기
}
Channel Buffering
Unbuffered Channel
- 하나의 수신자가 데이터를 받을 때까지 송신자의 채널에 묶임
- 즉 위에서 보여준 예시가 Unbuffered Channel 임
- 만약 수신자가 준비되지 않았다면 에러 발생
- Deadlock
func main() {
channel := make(chan int)
channel <- 1 // 수신 Goroutine이 없으므로 DEADLOCK
fmt.Println(<- channel) // 별도의 Goroutine이 없으므로 DEADLOCK
}
Buffered Channel
- 버퍼 채널을 만들어서 사용하면 수신자가 없어도 데이터를 보낼 수 있음
func main() {
channel := make(chan int, 2) // 두개의 버퍼 채널 생성
channel <- 10 // 수신자가 없더라도 보낼 수 있음
fmt.Println(<- channel)
}
송수신 역할 분리
- 채널은 기본적으로 송신과 수신 역할 전부 다 할 수 있다.
- 그러나 특정 역할만 수행하게 정해줄 수 있다.
func main() {
channel := make(chan string, 1) // Buffered Channel
sendChannel(channel) // 전송
receiveFromChannel(channel) // 수신
}
// 채널에 데이터 입력하는 역할만 수행
func sendToChannel(ch chan <- string ){
ch <- "data"
// data := <- ch 에러 발생
}
// 채널의 데이터를 수신하는 역할만 수행
func receiveFromChannel(ch <- chan string) {
data := <- ch
fmt.Println(data) // "data" 반환
}
채널 닫기
- 채널을 닫은 이후 더 이상 해당 채널로 데이터 전송은 불가하다
- 그러나 남은 데이터가 있다면 수신은 가능하다.
- channel의 리턴값은 두개이다
- 채널 내의 데이터 값과 수신 성공 여부
func main() {
channel := make(chan int, 2)
channel <- 1 // 채널에 데이터 전송
channel <- 3 // 채널에 데이터 전송
close(channel) // 채널 종료
fmt.Println(<-channel) // 남은 데이터가 채널에 있다면 수신
fmt.Println(<-channel) // 남은 데이터가 채널에 있다면 수신
if _, success := <- channel; !success { // 채널에 남아있는 데이터가 없다면 false
fmt.Println("데이터 없음")
}
}
728x90
반응형