Go

최근 수정 시각:

파일:나무위키프로젝트.png
이 문서는 나무위키 컴퓨터 프로젝트에서 다루는 문서입니다.
해당 프로젝트 문서를 방문하여 도움이 필요한 문서에 기여하여 주세요!

파일:나무위키+유도.png   바둑의 영문명인 Go에 대해서는 바둑 문서를 참조하십시오.

The Go Programming Language

파일:external/golang.org/frontpage.png

최초 개발자

로버트 그리즈머, 롭 파이크, 켄 톰슨

운영 및 개발

구글

공식 사이트

https://golang.org/

라이선스

BSD 라이선스

최신 버전

go1.10 (released 2018/02/16)


1. 내용2. 특징3. 예시4. 사용한 사례5. 참고6. 여담7. 관련 문서

1. 내용[편집]

구글이 2009년에 만든 프로그래밍 언어. 로버트 그리즈머, 롭 파이크, 켄 톰슨에 의해 디자인되었다.[1][2] 이름이 이름인만큼 검색이 불편한 경우가 제법 있다. 그래서인지 보통 Golang으로도 많이들 이야기한다.

Go 언어 사용자들을 고퍼(Gopher)라고 부르며, 고퍼들을 위한 연례행사인 고퍼콘(Gophercon)이 세계 각국에서 매년 열리고 있다.

2009년 11월에 첫 선을 보인 이래, 2014년 12월에 1.4 버전이 나온 데 이어 2015년 8월에 1.5 버전이 나왔다. 1.5 버전에서는 드디어 Go 컴파일러가 Go로 작성되었다.[3] 그 이전까지는 C언어로 작성되어 있었다. 자기 자신으로 구현된 컴파일러가 생겼다는 것은 개발 속도에 상당한 가속이 붙게 되었다는 뜻이라고 할 수 있다.[4] 2016년 2월 중순에는 HTTP/2가 기본으로 지원되고 템플릿 문법의 개선 등이 이루어진 1.6 버전이 출시되었고, 8월에는 컴파일 속도의 개선, 실행 퍼포먼스 향상, /x/net/context 패키지의 기본 패키지화 등이 이루어진 1.7 버전이 출시되었다. 여전히 1.4 버전에 비해 컴파일 속도는 느리다

2017년 2월 즈음에 32비트 MIPS 명령어 지원, 컴파일러 프론트엔드 추가[5], 가비지 컬렉션 개선, Cgo의 오버헤드 개선[6] 등의 변경점이 있는 1.8 버전이 출시되었다. 1.8 릴리즈 노트

전반적으로 C에서 영향을 많이 받았으며, 나온 지 5년 동안은 구글에 취직이라도 하지 않는 이상[7] 배워봤자 딱히 쓸 데가 없다는 이유로 새로운 언어에 관심이 많은 덕후얼리어답터 개발자들 사이에서나 알음알음 쓰이던 정도였지만, 다름아닌 구글이 만든 것이기도 하고, 언어 자체가 가진 매력도 있어서 사용자 층이 점차 늘어나는 추세다. 특히 Go 언어를 이용해서 안드로이드iOS 앱을 제작할 수 있게 적용 중이다.[8] 또한 Python이 그렇듯 웹 개발에도 쓰이고 있고, Revel, Beego 등의 풀 스택 프레임워크나 Gin 등의 마이크로 프레임워크들이 인기를 끌고 있다. Martini는 한국어 문서도 있다. 특히 서버 사이드 언어로서 좋은 평가를 받고 있는데, 대형 서비스가 아닌 간단한 웹사이트의 경우 Go가 자체적으로 지원하는 라이브러리와 Gorilla 같은 툴킷만으로도 쉽게 웹사이트를 만들어낼 수 있다. GoDoc이라는 Go 패키지 호스팅 사이트도 존재한다.

묘하게도 Go 언어는 중국에서 상대적으로 인기가 제법 있는 편이다.[9] 구글과 중국과의 관계 때문에 막혀 있었으나 https://golang.google.cn으로 이용 가능하게 되었다.

2. 특징[편집]

Go 언어의 특징은 컴파일 언어이지만 컴파일러의 컴파일 속도가 매우 빨라 인터프리터 언어처럼 쓸 수 있다는 점에 있다.[10] 이는 언어의 문법 구조를 개선함으로써 달성하였다. 컴파일러가 소스 코드를 해석하는 pass 수를 줄여서 달성한 것으로 보인다. 접근하기 어렵지 않고, 코드 역시 간결하면서도 컴파일 언어답게 높은 성능을 낼 수 있다는 점이 호평을 받는다. 자료형 체계에 있어 정적 타입(static type) 검사가 이루어지는만큼, Python 등에 익숙해져 있다가 넘어올 경우 조금 애로사항이 꽃필 수 있다. 간결하게 코드를 작성할 수 있으면서도 풍부한 라이브러리 등의 덕택에 막강한 기능을 쉽게 구현할 수 있다는 것은 큰 장점이다.

그러나 컴파일 언어의 태생적인 한계를 극복한 것은 아니라서 대형 모듈을 이것저것 붙이면 컴파일에 필요한 시간이 있기에 Python 등의 인터프리터 언어보다는 기계어 번역 시 확실히 반응이 늦다. 물론 컴파일 언어 중에서는 매우 빠른 편이지만 아무래도 인터프리터 언어의 즉흥성까지 바라는 건 무리. 대신 컴파일 언어인만큼 실행 시 퍼포먼스는 확실하다.

또한 Go는 GoRoutine이라는 비동기 메커니즘을 제공한다. 이 비동기 메커니즘은 Erlang에서 영향을 받은 것으로 각각의 고루틴은 병렬로 동작하며 메시지 채널을 통해 값을 주고받는다. 고루틴을 사용하면 이벤트 처리, 병렬 프로그래밍 등이 간단해진다. 단, 병렬화된 고루틴의 동기화 문제는 프로그래머가 챙겨 줘야 하며 동기화를 무시할 경우 프로그램이 비정상 종료될 수도 있다. 예를 들어 부모 루틴이 자식 루틴보다 먼저 끝나버리면 자식 루틴은 OS에 의해 메모리에서 강제로 사출되어 버린다. 그래도 동기화 방법은 기존 멀티스레드 응용프로그램에 비해 매우 간단한 편. 단순히 고루틴으로부터 반환값을 받는 줄을 메인 스레드에 추가하면 된다.

고루틴은 멀티스레드 메커니즘이지만 자체적인 스케줄러에 의해 관리되는 경량 스레드이며 OS에서 관리하는 경량스레드보다 더 경량이다.[11] 따라서 고루틴은 CPU 코어수와 무관하게 수백 수천만 고루틴을 작성해도 성능에 문제가 생기지 않는다. 이는 Erlang도 마찬가지.

Go는 바이너리 컴파일러이므로 서로 다른 머신 플랫폼들을 타겟으로 배포해야 할 경우 환경변수(GOOS와 GOARCH 등)를 그에 맞게 설정한 후 컴파일해서 여러 벌의 배포판을 만들어야 한다.

Go는 명시하고 있지 않지만 단순함과 실용성을 지향하는 언어다. keyword가 25개밖에 되지 않고 문법 또한 간결해 입문이 쉬운 편.

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

3. 예시[편집]

package main //패키지명이 main이 아닐 경우 에러가 발생한다.

import "fmt"
  
func main() {
    fmt.Println("Hello, world!")
}

  • Example of Printf

package main

import "fmt"

func main() {
    fmt.Printf("%d %d\n", 32, 132);
}

  • Hello world example of Cgo[12]


package main

/*
#include <stdio.h>
*/
import "C"

func main() {
    C.puts("Hello world")
}

  • Example of goroutine: http


package main

import (
    "fmt"
    "net/http"
)

var c = make(chan *http.Response)

func head(url string) {
    resp, _ := http.Head(url)
    c <- resp
}

func main() {
    // HEAD 요청을 동시에 실행한다.
    go head("https://namu.wiki")
    go head("https://www.google.com")
    go head("https://golang.org")

    for i := 0; i < 3; i++ {
        resp := <-c
        if resp != nil {
            resp.Body.Close()
            fmt.Printf("%v: %s\n", resp.Request.URL, resp.Status)
            continue
        }
        fmt.Printf("%v: 연결 실패\n", resp.Request.URL)
    } 
}

  • Example of select statement: timeout


package main

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

func main() {
    c := make(chan string)
    go func() {
        resp, err := http.Head("https://namu.wiki")
        if err == nil {
            resp.Body.Close()
            c <- resp.Status
            return
        }
        c <- "연결 실패"
    }()

    // 연결 시간 초과 알림을 select 로 구현할 수 있다.
    select {
    case status := <-c:
        fmt.Println(status)
    case <-time.After(2 * time.Second):
        fmt.Println("시간 초과")
    }
}

4. 사용한 사례[편집]

컨테이너 기반 가상화 도구인 Docker를 작성하는데 사용된 언어로 유명하다.

그리고 전부를 Go로 만든 것은 아니지만, 당연히 구글을 비롯해[13] 드롭박스클라우드플레어[14], 사운드클라우드, 넷플릭스 등에서도 기존의 기능들 중 상당수를 새롭게 Go를 이용해 바꿨다고 한다. 트위치TV도 많은 부분이 Go로 작성되었다고 하며, 언론사인 뉴욕 타임즈에서도 Gizmo라는 API 백엔드 서비스를 Go를 이용해 만들어 그 소스를 GitHub에 공개한 바 있고, SpaceX에서도 원격 측정 프로그램에서 Go를 사용한다고 한다.

5. 참고[편집]

컴파일 언어인 덕분에, 속도가 느린 스크립트 언어에서 연산 퍼포먼스가 필요한 부분을 Go로 대체해 넣을 수도 있다. 예를 들면, Go로 만든 코드를 공유 라이브러리로 컴파일해 Ruby에서 FFI를 이용해 컴파일한 .so 파일을 가져와 사용하는 식. PHP에서도 역시 가능하다.[15] 다만 기본 패키지들은 대개 성능보다는 편의성에 초점을 맞춘 탓에 극한의 성능을 추구하는 경우라면 사용을 권하기 어려운 것들이 있다. 예를 들면 웹 서버 제작시에 쓰이는 net/http나 html/template 등이 그러한데, 이런 경우엔 기본 패키지를 대체하는 별도의 패키지를 이용하면 (실제 체감효과는 별론으로 하되) 벤치마크상으로는 심지어 수십 배나 수치가 좋아지는(...) 경우도 있다.[16]

Go 언어의 설계 지향점은 시스템 프로그래밍 언어였으나, 가비지 컬렉션의 지원이나 제네릭의 부재로 인해 박싱/언박싱이 불필요하게 많이 일어나는 등 C/C++을 대체할 수 있는 언어는 아니라는 것에 합의가 이루어지고 있는 상황이다. 실제로 고성능 연산에 사용하기에는 C/C++에 비해 너무 느리며, 저수준 시스템 개발에서는 가비지 컬렉션과 고루틴을 지원하기 위한 무거운 런타임 등으로 인해 사용이 불가능에 가깝다. 그런 이유로 대체로 개발 속도와 실행 속도, 병행성 사이의 적정 지점이 필요한 서버 애플리케이션 개발에 많이 사용되는 편. 이전 버전에서는 저수준 시스템 프로그래밍에서도 C/C++보다 낫다는 식의 서술이 있었으나, 이는 Go를 개발하던 당시 개발진의 목표였을 뿐 이를 실제로 달성했다고 보는 사람은 드물다.

또 다른 비판점 하나로는 현대 프로그래밍 언어 연구의 성과를 일체 무시한 언어 설계. 많은 종류의 프로그램 버그는 프로그래밍 언어 차원에서 원천적으로 차단될 수 있으며, 프로그래밍 언어 연구자들은 쓰기 쉬우면서도 최대한 많은 버그를 컴파일 시점에 잡을 수 있는 타입 시스템을 만드는데 많은 노력을 기울이고 있다. 하지만 이런 노력들이 무색하게 Go에서는 널 포인터나 안전하지 않은 타입 캐스팅을 유발하는 인터페이스, 타입 세이프티한 제네릭의 부재 등 수많은 버그의 원천들에 전혀 손을 대지 않았다는 것.[17] 물론 단순성을 중시하는 Go의 철학상 최첨단 연구 성과들을 즉시 도입하는 데에는 무리가 있겠지만, 3~40년 전의 연구를 기반으로 최근 업계에서 당연하게 여겨지는 원칙들조차 전혀 고려하지 않았다는 것은 수많은 사람들에 의해 비판받은 바 있다. 이에 대해 구글은 제네릭을 지원하면 코드가 더 짧고 간결해지지만 Go는 지금도 코드가 긴 편이 아니고, 제네릭을 지원하면 컴파일 속도와 실행속도가 느려지기 때문에 지원하지 않는다고 밝힌 적이 있다.

Go를 지원하는 통합 개발 환경(IDE)으로는 JetBrains의 GoLand, 또는 IntelliJ IDEA의 Go 플러그인이 가장 높은 평가를 받는다. 대신 유료다. 무료 IDE를 찾는다면 이클립스나 LiteIDE를 쓰면 된다.

6. 여담[편집]

파일:2017-01-30_145609.png
2016년 중반부터 CMS와 microservices을 필두로 사용 영역 및 점유율이 급격히 높아지고 있다. 2016년 1월과 2017년 1월을 비교했을때 점유율은 0.161%에서 2.325%로 순위는 54위에서 13위로 올랐다. 스택 오버플로우에서 실시한 2017년 미국 개발자들 대상 설문조사에서는 평균 연봉 1위(11만불)의 언어로 기록되기도.[18] 구글 직원들이 쓰니까 그렇지

1.8 버전까지의 net 패키지에서 net.go를 열어보면, aLongTimeAgo라는 유닉스 시간 233431200의 값을 가지는 변수가 들어 있다. 오래 전의 시각을 미리 설정해 둔 것.[19] 그런데, 이것이 라즈베리 파이에서 발생시키는 문제가 발견되어 일단 1.9 버전 마일스톤에서는 233431200에서 그냥 1로 수정될 예정이다.

겨울왕국Write in Go Let It Go를 패러디한 아래와 같은 노래도 있다.
사실 C언어의 Write in C를 패러디 한 것이다. 자세한 내용은 문서 참고



번역:

The schedule's tight on the cluster tonight
분산환경에서 해야 할 일로 쉴 틈 없을 오늘밤
So I parallelized my code
그래서 저는 병렬화된 코드를 작성했지요
All those threads and continuations
그 모든 스레드와 연속성[20]들로
My head's going to explode
제 머리는 폭발하기 일보직전이랍니다
And all that boilerplate
심지어 그 모든 의례적인 코드[21]
That FactoryBuilderAdapterDelegateImpl
그 모든 "괴상야릇한디자인패턴의복잡다단한구현의향연"
Seems unjustified
이건 제가 가야 할 길이 아닌 것만 같아요
Give me something simple
좀 더 간결한 길을 알려주시겠어요?

Don't write in Scheme
Scheme 쓰지 마세요
Don't write in C
C로 짜지 마세요
No more pointers that I forget to free()
해제하길 깜빡한 포인터여 이제 그만 안녕 스마트 포인터라면?
Java's verbose, Python's too slow
Java는 장황하고, Python은 느려터졌단 걸
It's time you know
이제 깨달을 때가 왔어요

Write in Go! Write in Go!
Go로 짜세요, Go로 짜세요!
No inheritance anymore
클래스 상속이여 이제 그만 안녕
Write in Go! Write in Go!
Go로 짜세요, Go로 짜세요!
There's no do or while, just for
do도 while도 없어, 오직 for뿐
I don't care what your linters say
당신의 linter[22]가 뭐라 불평하든 상관없어요
I've got tools for that
제겐 해결책이 있답니다
The code never bothered me anyway
코드 자체가 신경 쓸 일을 만들지 않을테니 말이죠

7. 관련 문서[편집]

[1] 데니스 리치와 함께 유닉스 운영체제, C를 만든 그 사람 맞다(1943년생). 2007년 경에 이들 세 사람이 새로운 언어에 대한 스케치를 하면서 프로젝트가 시작되었다고 한다.[2] 지금도 패키지에 무엇을 포함할지는 이 세 사람이 만장일치로 합의해야 이뤄진다고 한다.[3] 다만 이 때부터 컴파일에 걸리는 속도가 약간 떨어졌다는 불평을 흔히 찾아볼 수 있다. 벤치마크 자료들에 따르면 1.4.3 버전이 1.5나 1.6 버전보다 컴파일에 걸리는 시간이 2~3배씩이나 빠르다는 것들도 흔히 보인다. 2016년 8월에 배포될 1.7 버전에서 이 문제는 어느 정도 개선될 것으로 보인다. 사전 공개된 1.7 베타 버전에서는 컴파일 속도가 1.6.2 버전에 비해 3분의 2 이하로 줄어들었다는 벤치마크 자료들이 보인다. 이후 공식적으로 밝힌 바에 의하면 1.6 대비 1.7은 20~30%가 감소했다고 한다.[4] 부트스트래핑(Bootstrapping) [5] 약 15%가 빨라졌다고 한다.[6] 약 절반 수준으로 줄어든다고 한다.[7] 구글 내부에서는 이걸 시스템 프로그램용으로 일부 사용하고 있다고 한다.[8] https://github.com/golang/go/wiki/Mobile[9] http://100coding.com/go/posts/1 https://www.reddit.com/r/golang/comments/23c7y0/why_is_golang_popular_in_china/cgvkppp[10] 사실 C++의 컴파일 속도가 복잡한 문법으로 인해 매우 느린 것이다.[11] 약 8kbyte[12] Go의 C 코드를 위한 FFI(Foreign Function Interface)이다.[13] 구글의 파일 다운로드 서버인 dl.google.com도 Go로 되어 있는데, 덕분에 간혹 해외 커뮤니티에서는 기본 net/http 패키지의 성능에 대해 의문을 표하면 dl.google.com조차 기본 패키지로 잘만 쓰는데 뭐라고? 같은 반응이 나타나기도 한다.[14] Go 기본 패키지 중 crypto 관련 처리 속도가 클라우드플레어 정도의 대형 서비스가 쓰기에는 최적화되지 않은 면이 있어 자체적으로 이 부분을 개선한 것을 배포하고 있기도 하다.(1.4 버전 기준)[15] 그 반대도 가능하다. PHP를 예로 들면, libphp5.so를 이용해 Go에서 PHP 코드를 불러와 실행하는 식이다.[16] 예를 들어 html/template의 경우 성능 저하의 주범으로 여겨지는 reflect를 사용해서 템플릿을 생성할 때 (코드 작성자 입장에서는 할 일이 줄어서 편리하지만) 자동으로 모두 이스케이프 처리를 해서 렌더링을 하므로 속도가 느려지게 된다. 당연하지만 이런 대체 패키지들을 쓰게 되면 대신 코드 작성은 조금 귀찮아지게 되고, 또한 기본 패키지의 문법이 호환되지 않는 경우도 잦다. 다만, 실제 서비스를 구성할 때에는 통상적으로 템플릿 캐싱을 추가할 것이므로 느린 파싱 속도는 사실 문제가 되지 않는다. net/http의 경우에도 Nginx 못지 않은 성능을 보여주는 대체 패키지가 존재한다. 이런 물건들을 사용한 몇몇 프레임워크들은 유독 벤치마크 그래프가 하늘을 뚫을 기세로 눈에 띈다(...).[17] 사실 이러한 구조는 Go의 모티브가 된 C도 동일하게 가지고 있다. 하지만 C는 20세기의 언어이고 Go는 21세기에 나온 언어라는 것이 문제.[18] http://stackoverflow.com/insights/survey/2017[19] 스타워즈 4가 A long time ago, in a galaxy far, far away....라는 스타워즈 시리즈의 전통의 오프닝과 함께 미국에서 개봉된 시각이다.[20] 원래 "프로그램의 현재 상태에 비추어 앞으로 실행해야 할 나머지 코드들을 의미한다"라고 되어있었는데, 완전히 틀린 이야기다. Continuation은 코드의 흐름에서 마음대로 멈추고 다시 진행("continue")할 수 있는 상태를 나타낸다. 가장 대표적인 예로 코루틴(루틴 A를 돌리다 중단하고 B로 가고, 잠시 후 B를 돌리다 중단하고 A에서 잠시 멈췄던 곳에서 그대로 진행하는 식)이 있다. 밑에 적힌 프로그래밍 언어 Scheme에서 최초로 사용된 개념인데, 쓰다 보면 코드가 꼬이기 마련이다.[21] 상용구 코드 참고[22] 프로그래밍 언어의 문맥(syntax)이나 의미론(semantics)의 부적절성, 오류 등을 귀뜸해 주는 유틸