[Go] Go Routine과 Channel 사용

2020. 2. 9. 20:11Go

반응형

0. goroutine의 개념

고루틴(이하 goroutine)은 Go 런타임이 관리하는 논리적 쓰레드입니다.

고루틴은 OS의 쓰레드 보다 훨씬 가볍게 비동기 처리를 구현하기 위해 만든 것으로 OS 쓰레드 보다 많은 면에서 우월성을 드러내고 있습니다.

예시로, 고루틴은 OS쓰레드와 1대1로 대응되지 않고, 훨씬 작은 공간을 차지 합니다 그리고 고루틴은 메모리 측면에서도 효율적입니다. 일반적으로 OS쓰레드가 1메가바이트의 스택을 차지하는 반면, 고루틴은 몇 키로바이트의 작은 스택을 갖습니다.

이제, 간단한 프로그램을 고루틴을 사용하여 더 빠르게 만들어 보도록 하겠습니다.


1. non-goroutine 프로그램 작성

간단한 윈도우 커맨드 프로그램의 명령어 중 하나인, ping을 따라하는 프로그램을 만들어 보겠습니다. http패키지의 get으로 해당 url의 웹사이트 접속이 원활한지 확인하는 것인데요, 코드는 아래에 적어두었습니다.

package main

import (
	"fmt"
	"net/http"
)

var results = map[string]string{}

func main() {
	urls := []string{
		"http://segreta.club/",
		"https://www.google.co.kr/",
		"https://www.instagram.com/",
	}

	for _, url := range urls {
		results[url] = hitURL(url)
	}
}

func hitURL(url string) (status bool){
	res, err := http.Get(url)

	if err != nil || res.StatusCode >= 400 {
		status = false
	}
	status = true
    
    return
}

위 프로그램에 따르면, 정상적으로 접속이 되는 사이트는 results[url]에 true의 값이 쓰여져 있을 것 이라는 것을 예상 할 수 있습니다. 하지만 이 프로그램의 최대 단점은, '느립니다' 하나의 url에 대한 요청을하고, 또 다시 다음 루프로 갑니다. 이런 절차적인 코드로는 시간이 urls의 크기에 비례하는 결함이 생깁니다.


2. goroutine으로 바꾸고, channel을 이용해 main함수와 값을 주고받기

위 전체코드에서 약간만 코드를 바꾸겠습니다. hitURL함수의 리턴을 없애고, 한개의 전송 전용 chan bool을 매개변수에 하나 더 받아 그것으로 goroutine이 끝났을때 값을 전하도록 하겠습니다. 그리고, main함수의 hitURL 호출 구문에서도 앞에 go라는 표현식을 추가 하겠습니다.

var results = map[string]bool{}

func main() {
	channel := make(chan bool)
	urls := []string{
		"http://segreta.club/",
		"https://www.google.co.kr/",
		"https://www.instagram.com/",
	}

	for _, url := range urls {
		go hitURL(url, channel)
	}

	for i := 0; i < len(urls); i++ {
		results[urls[i]] = <-channel // <-채널의 의미는, stack의 pop을 생각하시면 되겠습니다.
	}

	fmt.Println(results)
}

//hitUrl gets status code
func hitURL(url string, c chan<- bool) { //chan<- bool, bool 타입의 전송전용채널이 적당한 것 같습니다.
	res, err := http.Get(url)
	result := true
	if err != nil || res.StatusCode >= 400 {
		result = false
	}
	c <- result
}

코드를 실행하여 결과를 본다면, 기존에는 모두 한개, 또 한개, 그 다음 한개 이런식으로 순차적으로

일방적 진행이 되었던 반면, 이것은 모두 동시에 실행되고, 차례대로 순서를 마쳐 값을 얻는 모습입니다.

 

감사합니다.

반응형