우분투에서 첫 번째 동시성 Go 프로그램 작성하기

구글의 Go 프로그래밍 언어는 2009년부터 존재해 왔으며 2012년에는 공식 v1.0 상태에 도달했습니다. 그 사이에 많은 변화가 있었고 언어 설치 방법도 포함됩니다. 초기에는 공식 바이너리 배포판이 없었고, 소스 코드에서 Go를 빌드해야 했습니다. 이는 언어가 자주 변경되었기 때문에 권장되는 방법이었으며, 또는 리눅스 배포판에 대한 미리 빌드된 패키지를 사용해야 했습니다. 그 당시 윈도우 지원은 제한적이었고 인텔 이외의 CPU 아키텍처에 대한 지원도 제한적이었습니다.

그 이후로 상황은 크게 개선되었습니다. 리눅스에서는 Go를 설치하는 두 가지 쉬운 방법이 있습니다. Go 다운로드 페이지에서 공식 리눅스 바이너리 빌드를 다운로드하거나 리눅스 배포판에 대한 미리 빌드된 패키지를 선택하세요. 우분투에 Go를 설치하는 가장 쉬운 방법은 apt-get을 사용하는 것입니다:

sudo apt-get install golang

Go가 설치되면 프로그램 개발을 시작할 수 있습니다. 가장 간단한 Go 프로그램 중 하나는 고전적인 “Hello World!” 프로그램입니다. 텍스트 편집기를 사용하여 다음 짧은 Go 코드로 “ hellomte.go “라는 파일을 만드세요:

package main  
  
import "fmt"  
  
func main() {  
     fmt.Println("Hello Make Tech Easier!")  
}

Go의 v1.0 이후로 개별 컴파일 및 링크 명령의 필요성이 제거되었고 이전의 8g8l 명령은 go 명령으로 대체되었습니다.

hellomte.go를 실행하려면 터미널을 열고 소스 코드 파일이 있는 폴더로 디렉토리를 변경한 다음 다음을 입력하세요:

go run hellomte.go

이렇게 하면 Go 프로그램이 컴파일되고 실행되지만 실행 가능한 바이너리는 생성되지 않습니다. 바이너리를 생성하고 실행하려면 go build 명령을 사용하세요:

go build hellomte.go  
./hellomte

동시성의 힘

Go 프로그래밍 언어의 정의적인 특징 중 하나는 동시성을 지원한다는 것입니다. 이는 프로그램이 여러 작업을 동시에 수행할 수 있게 해줍니다. 동시성과 유사한 병렬성은 프로그램이 많은 작업을 동시에 실행할 수 있게 하지만, 동시성은 이러한 개별 작업이 서로 통신하고 상호작용할 수 있게 해줍니다. 그 결과, Go는 프로그래머가 작업자 풀, 파이프라인(하나의 작업이 다른 작업 후에 발생하는 경우) 및 동기 또는 비동기 백그라운드 작업을 포함한 다양한 동시 디자인을 사용할 수 있게 합니다. 이러한 동시성의 기초는 goroutinechannels, 그리고 Go의 select 문입니다.

다음은 동시 goroutine을 사용하여 문자열을 여러 번 출력하는 간단한 Go 프로그램입니다:

package main  
  
import (  
"fmt"  
"time"  
)  
  
func say(s string) {  
for i := 0; i < 5; i++ {  
        fmt.Println(s)  
}  
}  
  
func main() {  
go say("Hello Make Tech Easier!")  
    fmt.Println("조금 자고...")  
    time.Sleep(100 * time.Millisecond)  
}

say() 함수는 문자열(매개변수 s)을 다섯 번 출력하는 간단한 루프를 수행합니다. 흥미로운 점은 그 함수가 호출되는 방식입니다. 단순히 say("Hello Make Tech Easier!")를 호출하는 대신, 함수 호출 앞에 go 키워드가 놓입니다. 이는 함수가 별도의 작업으로 실행된다는 것을 의미합니다. 그런 다음 main() 함수의 나머지는 goroutine이 완료될 시간을 주기 위해 잠시 잠을 잡니다.

출력은 여러분을 놀라게 할 수 있습니다:

go-lang-concurrent

보시다시피 say() 함수는 goroutine으로 실행되며, 설정되는 동안 main() 함수의 나머지는 계속 진행되어 조금 자고...를 출력한 후 잠을 잡니다. 그때 goroutine이 활성화되어 문자열을 다섯 번 출력하기 시작합니다. 마지막으로 프로그램은 타임아웃 한계에 도달하면 종료됩니다.

채널

goroutines는 채널을 사용하여 통신할 수 있습니다. 채널은 Go 프로그램의 두 부분 간에 통신 라인을 엽니다. 일반적으로 함수는 goroutine으로 호출되며, 데이터(예: 네트워크 작업에서)를 다시 보내야 할 경우 채널을 사용하여 해당 데이터를 전달할 수 있습니다. Go 프로그램의 다른 부분이 해당 데이터를 기다리고 있다면, 데이터가 준비될 때까지 잠을 잡니다. 채널은 make() 함수를 사용하여 생성되며, goroutines에 매개변수로 전달될 수 있습니다.

다음 코드를 고려하세요:

package main  
  
import (  
"fmt"  
)  
  
func say(s string, c chan int) {  
var i int  
for i = 0; i < 5; i++ {  
          fmt.Println(s)  
}  
     c <- i  
}  
  
func main() {  
     c := make(chan int)  
go say("Hello Make Tech Easier!", c)  
     sts := <- c  
     fmt.Println(sts)  
}

say() 함수는 두 번째 매개변수가 채널이라는 점을 제외하고는 첫 번째 예와 매우 유사하며, 문자열을 출력한 후 반복 횟수를 c <- i 코드 줄을 통해 채널로 전송합니다.

메인 함수는 채널을 생성하고 say() 함수를 goroutine으로 시작한 다음, 데이터가 채널을 통해 올 때까지 기다립니다. sts := <- c 이후 결과를 출력합니다.

결론

Go 언어는 지난 몇 년 동안 크게 발전했습니다. 최근에 살펴보지 않았다면 지금이 좋은 시점일 수 있습니다!