티스토리 뷰
Go에서 채널(Channels)은 고루틴(Goroutines) 간에 데이터를 주고받을 수 있는 파이프라인을 제공합니다. 채널을 통해 고루틴은 안전하고 쉽게 통신할 수 있으며, 동기화 문제를 해결할 수 있습니다.
채널의 기본 개념
채널은 데이터를 보내고 받을 수 있는 타입 안전한 큐(queue)로, 두 고루틴 간의 통신을 가능하게 합니다. 채널은 chan 키워드를 사용하여 생성됩니다.
채널 생성
채널을 생성하는 방법은 다음과 같습니다:
ch := make(chan int) // int 타입의 채널 생성
채널에 데이터 보내기 및 받기
채널을 통해 데이터를 보내고 받는 방법은 다음과 같습니다:
데이터 보내기
ch <- value // value를 채널 ch로 보냄
데이터 받기
value := <-ch // 채널 ch로부터 데이터를 수신하고 value에 저장
예제: 간단한 채널 사용
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
go func() {
ch <- 42 // 채널로 데이터 보내기
}()
value := <-ch // 채널로부터 데이터 받기
fmt.Println(value)
}
위 예제에서 고루틴은 채널 ch에 42를 보냅니다. 메인 고루틴은 채널 ch로부터 데이터를 받아 출력합니다.
버퍼링된 채널
채널은 버퍼링될 수 있습니다. 버퍼링된 채널은 버퍼 크기만큼 데이터를 수신자가 준비되지 않았더라도 보낼 수 있습니다.
버퍼링된 채널 생성
ch := make(chan int, 2) // 버퍼 크기가 2인 채널 생성
예제: 버퍼링된 채널
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 2)
ch <- 1
ch <- 2
fmt.Println(<-ch)
fmt.Println(<-ch)
}
위 예제에서 버퍼 크기가 2인 채널을 생성하고, 두 개의 값을 보낸 후 두 개의 값을 받습니다.
채널 닫기
채널을 닫으면 더 이상 데이터를 보낼 수 없습니다. 그러나 닫힌 채널로부터 여전히 데이터를 받을 수 있으며, 모든 데이터를 받은 후에는 채널이 닫혔음을 알 수 있습니다.
예제: 채널 닫기
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
go func() {
for i := 0; i < 5; i++ {
ch <- i
}
close(ch) // 채널 닫기
}()
for i := range ch {
fmt.Println(i)
}
}
위 예제에서 고루틴은 5개의 값을 채널에 보내고 채널을 닫습니다. 메인 고루틴은 range를 사용하여 채널로부터 모든 값을 받습니다.
select 문
select 문은 여러 채널 연산을 기다리는 데 사용됩니다. 이는 복잡한 동기화 문제를 해결하는 데 유용합니다.
예제: select 문 사용
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
ch1 <- "one"
}()
go func() {
time.Sleep(2 * time.Second)
ch2 <- "two"
}()
for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println("Received", msg1)
case msg2 := <-ch2:
fmt.Println("Received", msg2)
}
}
}
위 예제에서 두 개의 고루틴이 각각 1초와 2초 후에 값을 채널에 보냅니다. 메인 고루틴은 select 문을 사용하여 두 채널 중 어느 하나로부터 값을 수신할 때까지 기다립니다.
채널 활용 예제
작업 분산
채널을 사용하여 작업을 여러 고루틴에 분산할 수 있습니다.
package main
import (
"fmt"
"sync"
)
func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
for j := range jobs {
fmt.Printf("worker %d started job %d\n", id, j)
results <- j * 2
fmt.Printf("worker %d finished job %d\n", id, j)
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
var wg sync.WaitGroup
for w := 1; w <= 3; w++ {
wg.Add(1)
go worker(w, jobs, results, &wg)
}
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
wg.Wait()
close(results)
for result := range results {
fmt.Println(result)
}
}
결과
worker 3 started job 1
worker 3 finished job 1
worker 3 started job 4
worker 3 finished job 4
worker 3 started job 5
worker 3 finished job 5
worker 2 started job 3
worker 2 finished job 3
worker 1 started job 2
worker 1 finished job 2
2
8
10
6
4
위 예제에서 3개의 워커 고루틴이 5개의 작업을 수행하고 결과를 출력합니다.
요약
- 채널: 고루틴 간의 통신을 위한 파이프라인.
- 버퍼링된 채널: 수신자가 준비되지 않았더라도 데이터를 보낼 수 있음.
- 채널 닫기: 더 이상 데이터를 보낼 수 없지만, 닫힌 채널로부터 여전히 데이터를 받을 수 있음.
- select 문: 여러 채널 연산을 기다리는 데 사용됨.
- 작업 분산: 채널을 사용하여 작업을 여러 고루틴에 분산 가능.
채널은 Go에서 고루틴 간의 안전한 통신과 동기화를 위한 강력한 도구로, 이를 잘 활용하면 병렬 처리를 효율적으로 구현할 수 있습니다.
GIT : https://github.com/kkaok/study-golang/tree/master/src/example/channel
출처 : chatGPT
'go' 카테고리의 다른 글
Go Http GET 요청 (0) | 2024.07.16 |
---|---|
Go 파일 읽고 쓰기 (0) | 2024.07.16 |
Go루틴(goroutine) (0) | 2024.07.12 |
Go defer, panic, recover (0) | 2024.07.11 |
Go 에러, 에러처리 (0) | 2024.07.11 |
- Total
- Today
- Yesterday
- 샘플
- AG-GRID
- 타임리프
- 그리드
- listToMap
- example
- 설정
- thymeleaf
- java
- Javascript
- lombok
- springboot
- 스프링부트
- UI
- RESTful
- 예제
- 메시지
- oracle
- ag grid
- SHEETJS
- cache
- 스프링
- REST
- spring
- mapToList
- sample
- Spring Boot
- mybatis
- restful서비스
- 엑셀
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |