채널 사용하기

이재홍 http://www.pyrasis.com 2014.12.17 ~ 2015.02.07

채널(channel)은 고루틴끼리 데이터를 주고 받고, 실행 흐름을 제어하는 기능입니다. 모든 타입을 채널로 사용할 수 있습니다. 그리고 채널 자체는 값이 아닌 레퍼런스 타입입니다.

먼저 채널을 그림으로 표현하면 다음과 같습니다.


그림 34-1 고루틴과 채널

채널은 다음과 같은 형식으로 사용합니다.

  • make(chan 자료형)

고루틴과 채널을 사용하여 두 정수 값을 더해보겠습니다.

package main

import "fmt"

func sum(a int, b int, c chan int) {
	c <- a + b          // 채널에 a와 b의 합을 보냄
}

func main() {
	c := make(chan int) // int형 채널 생성

	go sum(1, 2, c)     // sum을 고루틴으로 실행한 뒤 채널을 매개변수로 넘겨줌

	n := <-c            // 채널에서 값을 꺼낸 뒤 n에 대입
	fmt.Println(n)      // 3
}

출력 결과

3

채널을 사용하기 전에는 반드시 make 함수로 공간을 할당해야 합니다. 그리고 이렇게 생성하면 동기 채널(synchronous channel)이 생성됩니다.

다음과 같이 :=를 사용하지 않고, var 키워드로 채널을 선언하고 할당할 수도 있습니다.

var c chan int // chan int형 변수 선언
c = make(chan int)

sum 함수를 고루틴으로 실행하면서 더할 값과 채널 변수를 넣습니다. 채널을 매개변수로 받는 함수는 반드시 go 키워드를 사용하여 고루틴으로 실행해야 합니다.

go sum(1, 2, c)

함수에서 채널을 매개변수로 받을 때는 다음과 같은 형식으로 사용합니다.

  • 변수명 chan 자료형
//                         ↓ int형 채널을 매개변수로 받음
func sum(a int, b int, c chan int) {
	c <- a + b
//        ↑ 채널에 값을 보냄
}

채널에 값을 보낼 때는 다음과 같은 형식으로 사용합니다.

  • 채널 <- 값

채널 변수에는 =로 값을 대입하지 않고 <- 연산자를 사용합니다. 여기서는 sum 함수 안에서 ab를 더한 값을 채널 c로 보냅니다.

이제 main 함수에서는 채널에서 값을 가져옵니다.

  • <- 채널
n := <-c

이번에도 <- 연산자를 사용하지만 순서가 반대로 되어있습니다. 즉 채널 c에서 값을 가져온 뒤 변수 n을 생성하여 대입합니다(fmt.Println(<-c)처럼 변수에 대입하지 않고 바로 사용할 수도 있습니다).

<-c는 채널에서 값이 들어올 때까지 대기합니다. 그리고 채널에 값이 들어오면 대기를 끝내고 다음 코드를 실행합니다. 따라서 채널은 값을 주고 받는 동시에 동기화 역할까지 수행합니다.


그림 34-2 고루틴과 동기 채널의 흐름

요약하자면 다음과 같습니다.

  • 채널 <-: 채널에 값을 보냅니다.
  • <- 채널: 채널에 값이 들어올 때까지 기다린 뒤 값이 들어오면 값을 가져옵니다.
  • 가져온 값은 :=, =를 사용하여 변수에 대입할 수 있습니다.
  • 값을 가져오면 다음 코드를 실행합니다.

저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

01 June 2015