Go Channels
in Programming Language on Go
Channels?
Channel은 Goroutine과 메인함수 사이에 정보를 전달하기 위한 방법
혹은 Goroutine에서 다른 고루틴으로 커뮤니케이션하는 방법이다.
고루틴에서 메인함수, 고루틴에서 고루틴 모두 가능하다.
Channel은 일종의 파이프와 같다.
이 파이프를 통해 메시지를 보낼 수 있다.
package main
import fmt
func main() {
people := [2]string{"harry","minkuk"}
for _, person := range people{
go isSexy(person)
}
}
func isSexy(person string) bool {
time.Sleep(time.Seconds * 5)
return true
}
물론 위의 함수는 시작하자마 끝난다.
당연하다. 메인함수가 끝나버리기 때문에.
그런데 만약 여기서 파이프를 사용해서 isSexy
함수가 true
를 리턴하는지 보고싶다면 Channel을 사용하면 된다.
package main
import fmt
func main() {
c := make(chan bool)
people := [2]string{"harry","minkuk"}
for _, person := range people{
go isSexy(person,c)
}
result := <-c
fmt.Println(result)
}
func isSexy(person string, c chan bool) {
time.Sleep(time.Seconds * 5)
c <- true
}
Channel
을 사용하면 isSexy를 호출한 메인함수는 result := <-c에서 응답을 기다리게 된다.
고 런타임은 리시버(result := <-c)를 기다린다.
그런데 우리는 분명 2개의 메시지를 보냈는데 하나의 메시지만 받고 있다.
두개의 메시지를 받아보자.
package main
import fmt
func main() {
c := make(chan bool)
people := [2]string{"harry","minkuk"}
for _, person := range people{
go isSexy(person,c)
}
fmt.Println(<-c)
fmt.Println(<-c)
}
func isSexy(person string, c chan bool) {
time.Sleep(time.Seconds * 5)
c <- true
}
5초마다 하나씩 출력이 되는 것을 확인할 수 있다.
Go는 매우 똑똑해서 2개의 고루틴이 실행되고 있다는 것을 이미 알고 있다.
그래서 “2개의 메시지를 생성하겠구나“라고 생각한다.
만약 아래와 같은 상황이라면 어떨까?
package main
import fmt
func main() {
c := make(chan bool)
people := [2]string{"harry","minkuk"}
for _, person := range people{
go isSexy(person,c)
}
fmt.Println(<-c)
fmt.Println(<-c)
fmt.Println(<-c)
}
func isSexy(person string, c chan bool) {
time.Sleep(time.Seconds * 5)
c <- true
}
위의 실행결과는 에러를 발생시킨다.
그 이유는 Deadlock 때문인데, 기본적으로 메시지를 기다린다는 것은 Blocking Operation이다.
그렇기 때문에 Goroutine이 존재하지 않는데 메시지를 기다린다면 무한 대기 상태에 빠지기 때문에 Deadlock이 발생할 수 있다.
만약 호출하는 고루틴의 수가 늘어날때마다 그 수에 맞게 메시지를 호출하는 것은 불편하다.
그래서 아래와 같이 개선할 수 있다.
package main
import fmt
func main() {
c := make(chan bool)
people := [2]string{"harry","minkuk"}
for _, person := range people{
go isSexy(person,c)
}
for i:=0; i<len(people); i++{
fmt.Println(<-c)
}
}
func isSexy(person string, c chan bool) {
time.Sleep(time.Seconds * 5)
c <- true
}
이렇게 하면 간단하게 고루틴의 수의 맞게 메시지를 호출할 수 있다.
Reference
Nomad Coder - 니꼴라스 선생님