Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Archives
Today
Total
관리 메뉴

Code Habit

Go ) 보내기 전용 및 받기 전용 채널 사용 본문

카테고리 없음

Go ) 보내기 전용 및 받기 전용 채널 사용

코드베어 2020. 6. 10. 07:23

보내기 전용 채널과 받기 전용 채널은 값의 흐름이 한 방향으로 고정된 채널이다.

 

  • 보내기 전용( send-only ): chan <- 자료형 형식이다. c chan <- int는 int형 보내기 전용 채널 c를 뜻한다. 보내기 전용 채널은 값을 보낼 수만 있으며 값을 가져오려고 하면 컴파일 에러가 발생한다.
  • 받기 전용( receive-only): <-chan 자료형 형식이다. c <- chan int는 int형 받기 전용 채널 c를 뜻한다. 받기 전용 채널은 range 키워드 또는 <- 채널 형식으로 값을 꺼낼 수만 있으며 값을 보내려고 하면 컴파일 에러가 발생한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package main
 
import "fmt"
 
func producer(c chan <- int) { // 보내기 전용 채널
    for i := 0; i < 5; i++ {
        c <- i
    }
 
    c <- 100 // 채널에 값을 보냄
 
    // fmt.Println(<-c) // 채널에서 값을 꺼내면 컴파일 에러
}
 
func consumer(c <- chan int) { // 받기 전용 채널
    for i := range c {
        fmt.Println(i)
    }
 
    fmt.Println(<-c)    // 채널에 값을 꺼냄
 
    // c <- 1             // 채널에 값을 보내면 컴파일 에러
}
 
func main() {
    c := make(chan int)
 
    go producer(c)
    go consumer(c)
 
    fmt.Scanln()
}
 
// 실행 결과
0
1
2
3
4
100

 

이번에는 채널을 리턴값으로 사용해보겠다. 다음은 두 수를 더한 뒤 채널을 리턴한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
 
import "fmt"
 
func sum(a, b int<- chan int {
    out := make(chan int// 채널 생성
    go func() {
        out <- a + b // 채널에 a와 b의 합을 보냄
    }()
 
    return out         // 채널 변수 자체를 리턴
}
 
func main() {
    c := sum(12)    // 채널을 리턴값으로 받아서 c에 대입
    
    fmt.Println(<-c) // 3: 채널에서 값을 꺼냄
}

채널을리턴하려면 먼저 make 함수로 채널을 생성한다. 그리고 고루틴 안에서 채널에 값을 보낸 뒤 고루틴 바깥에서 채널을 리턴한다. 채널을 리턴값으로 받았으면 <-c처럼 값을 꺼내면 된다.

 

다음은 채널 매개변수와 채널 리턴값을 활용한 예제다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main
 
import "fmt"
 
func num(a, b int<- chan int {
    out := make(chan int)    // int 형 채널 생성
    go func() {
        out <- a    // 채널에 a의 값을 보냄
        out <- b     // 채널에 b의 값을 보냄
        close(out)    // 채널을 닫아서 range 키워드의 반복을 끝냄
    }()
    return out         // 채널 변수 자체를 리턴
}
 
func sum(c <- chan int<- chan int {
    out := make(chan int// int 형 채널 생성
    go func() {
        r := 0
        for i := range c {  // range를 사용하여 채널이 닫힐 때까지 값을 꺼냄
            r = r + i       // 꺼낸 값을 모두 더함
        }
        out <- r            // 더한 결과를 채널에 보냄            
    }()
    return out // 채널 변수 자체를 리턴
}
 
 
func main() {
    c := num(12// 1과 2가 들어 있는 채널이 리턴됨
    out := sum(c)   // 채널 c를 매개변수에 넘겨서 모두 더함
                    // 더한 값이 들어 있는 out 채널을 리턴
    
    fmt.Println(<-out) // 3: out 채널에서 값을 꺼냄
}