Go Channels

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 - 니꼴라스 선생님



© 2022. by minkuk

Powered by minkuk