이 글은 골든래빗 《Tucker의 Go 언어 프로그래밍》의 25장 써머리입니다.
var messages chan string = make(chan string)
messages <- "메시지"
var msg string = <- messages
func Test_GoroutineChannel(t *testing.T) {
ch := make(chan int)
go func() {
time.Sleep(4 * time.Second)
ch <- 1
}()
msg := <-ch //channel에 데이터가 들어올 때까지 대기한다.
t.Log(msg)
}
func Test_channel(t *testing.T) {
ch := make(chan int)
ch <- 9 //Deadlock 발생
fmt.Println("Never Print")
}
//버퍼를 가진 채널을 생성하는 법
var messages chan string = make(chan string, 2) //버퍼가 2인 채널 생성
func Square(wg *sync.WaitGroup, ch chan int) {
for n := range ch { //for range 를 사용하면 채널에서 데이터를 계속 기다릴 수 있다.
log.Printf("Square : %v", n*n)
time.Sleep(time.Second)
}
wg.Done()
}
func Test_WaitingChannel(t *testing.T) {
var wg sync.WaitGroup
var ch chan int = make(chan int)
wg.Add(1)
go Square(&wg, ch)
for i := 0; i < 10; i++ {
ch <- i * 2
}
close(ch)
wg.Wait()
}
for range로 채널에서 데이터를 계속 기다릴 수 있다. 하지만 wg.Wait()는 작업이 완료되기를 기다리는데, wg.Done()이 실행되지 않아 데드락이 걸린다.
탈출하고자 하는 경우, 채널에 데이터를 밀어넣는 오퍼레이션 종료 이후 채널을 닫아줘야 한다.
func Square(wg *sync.WaitGroup, ch chan int, quit chan bool) {
for {
select {
case num := <-ch:
log.Println(num)
case <-quit:
wg.Done()
log.Println("Quit")
return
}
}
}
func Test_channelSelect(t *testing.T) {
var wg sync.WaitGroup
ch := make(chan int)
quit := make(chan bool)
wg.Add(1)
go Square(&wg, ch, quit)
for i := 0; ; i++ {
ch <- i * i
if i >= 11 {
quit <- true
return
}
}
wg.Wait()
}