Golang

구글에서 개발한 언어. 로버트 그리즈머, 롭 파이크, 켄 톰슨에 의해 디자인되었다. 특히 켄 톰슨의 영향력이 이 언어 전반에서 드러나는데, 켄 톰슨은 데니스리치와 함께 C언어를 만들었던 사람이다. 정식이름은 “GO” 지만 일반동사인 go와 자주 혼동(특히 구글 검색시)되어서 “golang”으로 더 많이 불린다.

기본적으로는 컴파일언어이나, 최신 언어의 트렌드인지 강력한 타입 추론을 기반으로 마치 스크립트 언어처럼 사용할수 있다1. 모듈화가 잘 지원되고 배우기에도 쉽다. 이는 문법 자체가 간결하고 예외에서 벗어난 동작이 없어서 파싱과 컴파일 과정 자체의 Pass수가 줄어들어 일어난 일이다. 컴파일 언어인 만큼 실행성능이 어마어마한데 GC가 기본적으로 탑재됨에도 불구하고 성능별 언어순위에서 10위권 안에 들어가는 위엄을 보여준다.

2015년 8월 발표한 1.5버전에서는 go컴파일러를 go로 작성하였으며 이는 언어자체가 독립적으로 동작할수 있음을 의미하는 큰 변화점이라 할수 있다.

큰 특징 중 하나는 비동기-병렬화를 GoRoutine이라는 일종의 co-routine으로 처리하는데 2, 동기화 이슈는 Messaging 방식으로 처리한다. 이 GoRoutine는 초경량 쓰레드로 취급 될수 있으며, 따라서 수천개의 GoRoutine을 한번에 생성해도 별 무리 없이 처리한다. 아마 Erlang에서 영향을 받은듯… Messaging방식은 복잡한 세마포어나 크리티컬 세션과는 달리 간결한 처리를 제공하며 머리 싸매야 하는 경우가 줄었다.

주요 사용자로는 Docker가 있으며 주로 중국에서 인기가 많다.

https://golang.org/ref/spec

특징

Go Libs/Tools

go 언어에서 쓸만한 라이브러리와 툴들을 정리한다. 추천 순서대로 정렬 해 두었다. Awesome go랑은 달리 영 상태가 안좋아 보이면 과감히 제외 하였다.

Tip

Mutex or Channel

https://github.com/golang/go/wiki/MutexOrChannel

Golang에서는 channel 이라는 언어적 툴이 있다보니 이것을 사용하는것에 강한 유혹을 느끼곤 한다. 그러나 mutex와 배제적으로 사용할필요는 없다. channel은 메세지 큐이다. 즉 실제로 메세지를 전달해야 하는 경우에 사용 하면 좋다. 예를 들면 큐에 작업을 넣어 둔다던가, work에 작업을 맡기고 그 결과를 받아온다던가 하는 일에는 channel이 적절하다. 하지만 그렇지 않은 일에는 오히려 사용하면 코드가 복잡해진다. golang에서 channnel을 제공하는 것은 그것을 반드시 사용하라는 것이 아니라 필요할때 쓰라는 것이다. 만약 특정 데이터 테이블을 관리하는 코드를 짠다면 그냥 mutex가 더 맞을수 있다. 어떤것을 써야하는지를 알려면, 데이터의 주도권을 넘겨주는가 아닌가 이다. 만약 데이터의 주도권을 넘겨줘야 한다면 channel 이 더 알맞다. 만약 데이터의 주도권은 넘겨주지 않는다면, 그 경우에는 mutex가 더 적절하다.

profile

golang에 profile툴은 이미 마련되어 있다. 원격에서도 사용할수 있으니 그냥 가져다 쓰면 된다.

ld 관련 팁

golang은 libc 나 pthread 같은 리눅스에 기본으로 들어있는 라이브러리는 다이나믹링크를 시도한다. 이를 다음과 같은 flag를 줌으로써 static link 해둘수 있다.

-ldflags "-extldflags -static"

이때 다음과 같은 에러가 날수 있다.

/usr/lib/golang/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: cannot find -lpthread
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status

fedora에서는 glibc-static 을 설치하면 해결된다.

sudo dnf nstall glibc-static

https://stackoverflow.com/questions/16024978/usr-bin-ld-cannot-find-lc-while-compiling-with-makefile

channel types

channel 은 read only 나 write only의 type이 존재한다. 이를 활용하면 Event 시스템을 쉽게 만들수 있다.

참고 : https://golang.org/ref/spec#Channel_types

golang test benchmark

golang으로 벤치마크 테스트를 손쉽게 작성할수 있다. 평소 test case를 작성하고 있다면 별다른 노력 없이도 성능 측정이 가능하다. 타이머들을 쉽게 쓸수 있게끔 잘 해주기 때문에 편하다.

https://lk4d4.darth.io/posts/bench/

build 빠르게 하기

1.10 부터는 bulid cache가 도입되어서 incremental build 가 된다. 그전 버전은 build 시에 -i 옵션을 주면 된다. https://groups.google.com/forum/#!msg/golang-dev/qfa3mHN4ZPA/X2UzjNV1BAAJ https://ttboj.wordpress.com/2017/02/26/faster-golang-builds/

iota의 의미

https://stackoverflow.com/questions/31650192/whats-the-full-name-for-iota-in-golang

수학에서 쓴 i 라고 한다. 허수표현에 쓰거나 반복자를 표현하는 데 쓴다. 예를 들자면 여기에 쓰이는 i

go test cache disable

https://github.com/golang/go/issues/24573#issuecomment-427455066

–count 1 을 사용 하면 된다. cache disable 은 go mod 에서 문제를 일으킬수 있다.

그외

Gopath는 필수 인가.

안타깝게도 그러하다. 상황이 바뀌었다. go lang을 만들 사람들을 gopath를 강제했었지만, go 1.11 버전 부터는 go mod를 통해 go path 없이도 사용할수 있다. 다만 go mod 는 반대로 gopath 안에서는 동작하지 않기 때문에 go mod로 관리되는 repo는 gopath 밖에서 사용 해야 한다. 여전히 vendor는 gopath 밖에서는 동작하지 않는다. 참고 go mod 에는 vendor폴더를 만들어 주는 기능이 있기 때문에 go path 안에서는 이 기능을 활용해 볼수는 있다.

https://github.com/golang/go/issues/17271

See Also


  1. C나 Java의 컴파일 속도와 비교했을때 엄청나게 빠르다. 비슷한 동작을 하는 프로그램을 컴파일 해보면 10배 가까운 체감 속도 차이가 난다.
  2. 네이밍 센스가 참…
  3. 포인터 연산이 대부분 포인터에 대한 멘붕의 주범이자 실수하기 좋아서 이렇게 했다고 한다. 개인적으로는 레퍼런스와 복사본이 잘 구분되서 JAVA보다 좋은 방식이라고 생각한다.
  4. maintain 되지 않는다. 대신 gin 을 쓰면 된다.
  5. maintain 되지 않는다.
  6. 내가 만들었다.
  7. 개발중일때는 포함시키지 않아 컴파일 시간을 줄이고, 같은 인터페이스로 릴리즈에 사용할수 있어 정말 편하다.