Learning Go Language - Hello world, GoRoutine

요즘 Go langage를 배워볼까 합니다. 그래서 아주 천천히 틈날때마다 보고있는데, 조금씩은 정리해서 포스팅해볼까 합니다. 아마 익숙해지면 Ruby와 섞어서 코딩하게 될 것 같네요.

문법에 대한 설명은 패스하고 Go만의 특이한 부분들 위주로 글 작성해보죠. 그럼 시작합니다.

What is Go lang?

2009년 11월 구글이 공개한 프로그래밍 언어로 C 스타일의 문법을 가지며 점차 관심받고 있는 언어입니다. 대체로 Back-end단에서 서버 개발에서 좋은 평가를 받고있고, 모바일 앱 개발 지원쪽으로도 방향이 잡혀있는 걸로 알고 있습니다.

Go는 적은 수의 키워드를 사용하기 때문에 초반 러닝커브가 낮다고 생각합니다. 아래 항목들이 go 기본적으로 사용되는 키워드입니다.

  • break
  • default
  • func
  • interface
  • select
  • case
  • defer
  • go
  • map
  • struct
  • chan
  • else
  • goto
  • package
  • switch
  • const
  • fallthrough
  • if
  • range
  • type
  • continue
  • for
  • import
  • return
  • var

Helloworld

모든 언어의 시작은 Hello World에서 시작됩니다.

package main

import "fmt"

func main() {
    fmt.Println("Hello world!");
    fmt.Printf("%d",999);   
}

Package

Go에서는 package 키워드를 통해 프로그램이 시작된 패키지를 지정할 수 있습니다. 위에 Hello World 코드에선 main 패키지가 되겠지요. 추가적인 패키지는 import를 통해 로드할 수 있고, 타 언어에서 #include, require, import 등의 키워드와 비슷하다고 생각하시면 됩니다.

그럼 다른 패키지를 로드하면 모든 기능을 사용할 수 있을까요? 그건 보안적, 가용성 관련해서 문제가 발생할 수 있을 것 같고, 이는 각각 패키지에서 그 내용을 제어 할 수 있습니다. 바로 Exported name을 통해 제어합니다.

Exported name은 외부에서 로드했을 때 사용할 수 있는 메소드란 걸 알려주는 언어상의 규칙입니다. 예를들면 abc라는 패키지의 returnA라는 함수가 있다고 가정합니다.

func returnA{
  return "r-A" // 외부에서 호출이 불가능한 함수
}
func ReturnA{
  return "R-A" // 외부에서 호출이 가능한 함수
}

이런 경우 ReturnA만 외부에서 로드가 가능해집니다. class의 private, public 관계 생각하시면 이해에 도움됩니다.

GoRoutine

위에서 GoRoutine에 대한 이야기를 잠깐헀는데, 이야기를 더 이어가면 GoRoutine은 Go runtime 내부에서 관리되는 쓰레드. 아니 가상 쓰레드입니다. go 키워드를 통해 GoRoutine을 호출할 수 있으며 비동기로 동작되기 떄문에 쓰레드처럼 여러 코드를 동시에 실행할 수 있습니다.

package main

import (
    "fmt"
    "time"
)

func routine(s string) { // goRoutine을 통해 실행할 함수
    for i := 0; i < 8; i++ { // 그냥 루프 돌면서 숫자 찍는 함수
        fmt.Println(s, i)
    }
}

func main() {
    go routine("GoRoutine 1 : ") // 첫번째 루틴 실행
    go routine("GoRoutine 2 : ") // 두번쨰 루틴 실행
    time.Sleep(time.Second * 5)
}

다른 언어의 쓰레드와는 다르게 OS 쓰레드를 생성하는 것이 아닌 Go 자체에서 관리하는 가상의 쓰레드(?)를 만들어서 동작하게 됩니다. 그래서 다른 쓰레드나 멀티 프로세스와는 다르게 가볍고 동적으로 메모리 관리가 되어서 적은 메모리 사용, 때에 따라 동적으로 증가시켜 퍼모먼스 또한 유지합니다.

각 routine들간 데이터 공유는 Go 채널이란 것을 이용해서 이루어집니다. 이 친구는 routine을 만드는 Go runtime 하위에서 동작합니다.

다만 Go routine은 Go 자체가 디폴트로 한개의 CPU를 사용하도록 되어있기 떄문에 갯수가 많아져도 한개만 사용합니다. 그래서 조금 더 걍력한 퍼포먼스가 필요하다면 runtime 패키지의 GOMAXPROCS를 통해 사용할 CPU의 갯수를 늘려줄 수 있습니다.

package main

import (
    "runtime"
    "fmt"
    "time"
)

func routine(s string) { // goRoutine을 통해 실행할 함수
    for i := 0; i < 8; i++ { // 그냥 루프 돌면서 숫자 찍는 함수
        fmt.Println(s, i)
    }
}

func main() {
    runtime.GOMAXPROCS(2) // 스펙
    go routine("GoRoutine 1 : ") // 첫번째 루틴 실행
    go routine("GoRoutine 2 : ") // 두번쨰 루틴 실행
    time.Sleep(time.Second * 5)
}

Reference

  • https://go-tour-kr.appspot.com/#1