GoRoutine과 Channel

비동기 메커니즘 고루틴

goru01

GoRoutine과 Channel에 대해 알아보겠습니다.

GoRoutine

GoRoutine은 Go Runtime이 관리하는 논리적 혹은 가상적 Thread입니다.

Go에서 go 키워드를 사용하여 함수를 호출하면, 런타임 동안 새로운 goroutine을 실행합니다.

GoRoutine은 비동기적으로( asynchronously ) 함수를 실행하며 여러 코드를 동시에( Concurrently ) 실행하는 기능입니다.

또한, Goroutine은 함수 및 메소드를 다른 함수 및 메소드와 동시에( 병렬형 ) 사용 가능하게 하는 기능입니다.

GoRoutine은 OS Thread에 비해 엄청난 경량 Thread입니다. ( OS Thread : 1MB, GoRoutine : 2kb )

Go 런타임 상에서 관리되는 여러 GoRoutine들은 종종 하나의 OS Thread로 실행되고는 합니다.

즉 GoRoutine은 OS Thread와 1대1로 매칭되지 않고 Multiplexing으로 훨씬 적은 OS Thread를 사용합니다.

goru02

Channel

Go Channel은 해당 Channel을 통해 GoRoutine과 Goroutine 혹은 Main 함수 서로의 데이터를 주고받는 파이프 통로 입니다.

Channel은 make() 함수를 통해 미리 생성해야하며 채널 연산자( <- )를 통해 데이터를 보내고 받을 수 있습니다.

Channel은 상대편이 준비될 때까지 채널에서 대기하며 별도의 lock을 걸지 않고 데이터를 동기화 하는데 사용됩니다.

Channel로 데이터를 보낼때는

channel 변수명 <- 데이터 

와 같이 사용하고

데이터를 받을 때에는

<- channel 변수명

으로 사용합니다.

다음은 http.Get() 함수를 사용한 예제입니다.

package main

import (
	"errors"
	"fmt"
	"net/http"
)

type requestResults struct {
	url    string
	status string
}

var errRequestFailed = errors.New("Request failed")

// functional programing
func main() {
	// map이 초기화가 안되서 에러
	// var requestResultss map[string]string

	// make() 함수로 초기화
	var results = make(map[string]string)
	c := make(chan requestResults)

	urls := []string{
		"https://www.airbnb.com/",
		"https://www.google.com/",
		"https://www.amazon.com/",
		"https://www.reddit.com/",
		"https://www.google.com/",
		"https://soundcloud.com/",
		"https://www.facebook.com/",
		"https://www.instagram.com/",
	}

	for _, url := range urls {
		go hitURL(url, c)
	}
	for i := 0; i < len(urls); i++ {
		// fmt.Println(<-c)
		result := <-c
		results[result.url] = result.status
	}
	for url, status := range results {
		fmt.Println(url, status)
	}

}

func hitURL(url string, c chan<- requestResults) {
	resp, err := http.Get(url)
	status := "OK"
	if err != nil || resp.StatusCode >= 400 {
		status = "FAILED"
	}
	c <- requestResults{url: url, status: status}
}

goru03

urls Slice의 인덱스 순서와 관계없이 병렬형으로 결과값을 받는 것을 확인할 수 있습니다.

2개의 GoRoutine으로 데이터를 보낼 때

3개 이상으로 데이터를 받는다면

fatal error : all goroutines are asleep - deadlcok! 

데드락 예외가 발생합니다.

또한 main함수가 종료되지 않고 GoRoutine이 Channel을 통해 메세지를 받기 전까지 Main 함수를 멈추는 것을

Blocking Operation

이라고 합니다.

Copyright © Juwon. Built with Gatsby