Concurrency in Go

심우진·2022년 7월 16일
0

- Go 언어로 최신 컴퓨팅 환경이 당면한 과제 해결하기

C, C++ 같은 언어들은 빠른 수행 속도를 자랑하는 반면, Ruby나 Python 같은 언어들은
개발 기간이 짧다.
Go 언어는 이 둘 사이의 균형을 잘 맞추고 있어 빠른 수행 속도를 제공하면서도 개발 기간을 단축할 수 있는 다양한 기능들을 제공한다.

동적 언어로 어플리케이션을 작성하는 경우 높은 생산성을 기대할 수 있는데,
그 이유는 코드를 작성한 후 별다른 중간과정을 거치지 않고도 작성된 코드를 실행할 수 있기 때문이다.
반면, 동적 언어는 정적 언어들이 제공하는 타입 안전성을 제공하지 않으며,
실행 시에 잘못된 타입 때문에 발생할 수 있는 버그를 방지하기 위해
광범위한 테스트 코드를 작성해야 한다는 단점이 있다.
Go 언어에서는 이런 모호함 때문에 소중한 시간을 낭비하지 않아도 된다.
만일 개발자가 다른 타입의 값을 전달하면 컴파일러가 이를 자동으로 잡아내서 알려주기 때문이다.

- Concurrency

Go의 가장 강력한 기능 중 하나다.
고루틴은 스레드와 유사하지만 더 적은 메모리를 소비하며 더 적은 양의 코드로 구현 할 수 있다.
채널은 내장된 동기화 기능을 이용해 고루틴 간에 형식화된 메시지를 공유할 수 있는 데이터 구조다.
고루틴들이 필요한 데이터를 먼저 사용하기 위해 경쟁하게 하는 것이 아니라 고루틴 간에 데이터를 서로 전송할 수 있기 때문에 프로그래밍 도델이 더 간편해지는 장점이 있다.

고루틴

package main

import (
	"fmt"
	"time"
)

func main() {
	go sexyCount("nico")
	sexyCount("fly")
}

func sexyCount(person string) {
	for i := 0; i < 10; i++ {
		fmt.Println(person, "is sexy", i)
		time.Sleep(time.Second)
	}
}

채널

package main

import (
	"fmt"
	"time"
)

func main() {
	c := make(chan string)
	people := [3]string{"nico", "flynn", "larry"}
	for _, person := range people {
		go isSexy(person, c)
	}
	for i := 0; i < len(people); i++ {
		fmt.Println(<-c)
	}
}

func isSexy(person string, c chan string) {
	time.Sleep(time.Second * 5)
	c <- person + " is sexy"
}

ex)

package main

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

type requestResult struct {
	url    string
	status string
}

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

func main() {
	results := make(map[string]string)
	c := make(chan requestResult)
	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/",
		"https://academy.nomadcoders.co/",
	}

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

	for i := 0; i < len(urls); i++ {
		Result := <-c
		results[Result.url] = Result.status
	}

	for url, status := range results {
		fmt.Println(url, status)
	}
}

func hitURL(url string, c chan<- requestResult) {

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

0개의 댓글