Martin Heller | Australian Reseller News
2014.09.23
Go 프로그래밍 언어는 구글(Google)이 개발한 오픈소스 프로그래밍 언어로, 단순하며 신뢰성이 높고, 효율적인 소프트웨어 개발에 도움이 된다. 토니 호어가 고안한 통신 순차 프로세스(Communicating Sequential Processes, CSP)에 영향을 받은 프로그래밍 언어 중의 하나로, 오캄(Occam), 얼랑(Erlang), 뉴스퀵(Newqueak), 림보(Limbo) 또한 CSP에 영향을 받았다.
이 기사에서는 Go 언어의 차별화된 특징 몇 가지와 매우 간단한 동시성(Concurrency) 예시를 살펴보고자 한다. 현재 해당 프로젝트 참가자는 500명 이상으로, 플랜 9(Plan 9)과 인페르노(Inferno)를 공동 개발한 구글 엔지니어 롭 파이크가 주도하고 있다. editor@itworld.co.kr
슬라이스(slices)
Go 언어는 배열의 개념을 확장한 '슬라이스(slice)'를 이용한다. 'slice'는 값의 배열과 길이를 포함한다. []T는 자료형 T의 배열이라는 뜻이다. 예제와 같은 그림을 생성하기 위해 unsigned 된 바이트로 정의한 2차원 slice를 정의했다. 'package main'은 프로그램의 시작 위치를 나타낸다. ‘import’ 문은 C와 C++에서의 ‘include’을 확장한 버전으로, 여기에서는 머큐리얼(Mercurial) 저장소로부터 pic 파일을 얻는다. ‘:=’구문은 변수 선언 및 초기화를 하며, 컴파일러는 가능한 한가지 자료형을 참조한다. 'make'는 다른 형의 slice를 생성하는 데 이용된다. ‘for… range’는 C#에서 ‘for…in’ 반복문과 같다.
맵(maps)
Go 언어의 자료형 map은 값을 키에 맵핑한다. Slice와 마찬가지로 'new'가 아닌 ‘make’로 map을 생성한다. 이 예제는 문자열 키를 정수 값으로 맵핑하며, map 자료형으로 정의된 변수에 대한 삽입, 업데이트, 삭제를 실행한다.
구조체(Structs)와 메소드(Methods)
Go 언어에는 클래스(Class) 대신 이름과 자료형이 정의된 필드와 함수를 가진 구조체(Struct)가 있다. 메소드는 반환값이 있는 함수다. 메소드 선언은 메소드에 식별자(메소드 이름)을 붙이고, 메소드를 반환값 기본형에 연결한다.
예제에서는 2개의 부동 소수점 필드인 X와 Y, 메소드 Abs가 정의된 Vertex 구조체를 선언한다. 접근 제한자는 필드 첫글자로 구분한다. 첫글자가 대문자이면 ‘public’이며, 소문자이면 ‘private’다. 객체의 필드나 메소드는 도트 연산자(.)를 통해 접근할 수 있으며, ‘’C의 포인터 개념인 *와 &를 이용한다. 이 예제의 결과 값는 ‘5’이다.
인터페이스(Interface)
Interface 여러 메소드로 정의한 자료형이다. Interface는 메소드를 구현하는 그 어떤 값도 할당할 수 있다. 이 예시에서는 ‘Abser’라는 인터페이스를 정의했으며, Abser의 변수 a를 정의했다. 라인 17과 18에서는 값이 할당됐으나, 라인 22에서는 컴파일 단계에서도 값이 할당되지 않았다. 이전 슬라이드에서 본 Vertax의 Abs 메소드의 반환값은 Vertex형 포인터 값이므로, *Vertex는 Abser에 할당되지만, Vertex은 할당되지 않는다.
switch 문
Go 의 switch 문은 C와 유사한 다른 언어에서 쓰이는 switch 문과 비슷하나, Go의 case 문은 값뿐만 아니라, 타입 또는 식을 사용할 수 있다. case 문은 ‘fallthrough’ 문으로 끝나지 않는 한 'break'가 자동으로 걸린다. case 문은 정의된 순서대로 평가된다.
go 반복문(goroutine)
go 반복문(goroutine)은 토니 호어의 CSP 방식을 이은, 매우 가벼운 쓰레드(thread)다. 예제의 라인 16은 say 함수를 비동기식으로 호출하는 반면에, 라인 17은 say 함수를 동기식으로 호출한다. go 반복문, channel, select 문은 Go 언어의 확장성이 뛰어난 동시성의 핵심 요소들이며, 바로 이 점이 최대 장점이다. 전통적인 동기화 객체도 있으나 거의 필요 없다. 예제의 결과값은 ‘hello/world/hello/world/hello/world/hello/world/hello’다.
channel
Go 에서 channel 은 특정 자료형의 값을 송수신하는 방식으로 통신할 수 있는 함수에 관한 메커니즘을 제공한다. Channel의 초기값은 ‘0’이다. 라인 16을 보면 정수의 양방향 channel을 생성했다. 또한, 단방향 송신인 <-c와 단방향 수신인 c<- channel도 작성했다. 라인 17과 18에서는 slice로 정의된 a를 절반씩 나누고 비동기식으로 sum을 호출한다. 라인 19에서 정수 x와 y는 해당 channel로부터 2개의 sum을 수신한다. 라인 7에서 공백 식별자인 밑줄 표시(_)는 for..range 반복문에서 첫번째 인자 값을 무시한다는 의미다. 예제 프로그램의 결과값은 17 -5 12다.
range 와 close
송신부에서는 값이 더 이상 송신되지 않음을 알리기 위해 channel를 ‘close’할 수 있다. 수신부는 두 번째 매개변수에 수신 식을 지정함으로써 어떤 channel이 close 처리되었는지를 테스트할 수 있다. ‘i := range c’ 반복문은 close 처리될 때까지 channel 로부터 반복적으로 값을 수신한다. channel 의 ‘cap’ 은, channel 의 버퍼(Buffer)의 크기를 나타내는 용량이며, 라인 17 과 같이 channel 을 작성할 때 선택적인 두 번째 인수로 설정한다. 지정문의 컴팩트 형식은fibonacci 함수 안에 위치한다. 예제 프로그램의 출력값은 0부터 34중 피보나치에 해당하는 첫 10개의 숫자다.
선택 문(select)
select 문은 송신 혹은 수신 연산 중 하나를 선택한다. switch 문과 유사해 보이지만, select 문은 통신 연산를 참조한다. select 문은 case 문 가운데 하나가 실행되면 중단하고, 해당 case 문을 실행한다. 여러 개의 case 문이 실행 가능할 경우, 하나를 무작위로 선택한다.
여기에서 main 함수는 피보나치 함수를 호출한다. 여기에는 버퍼링 되지 않은 2개의 channel도 정의되는데, 하나는 결과 값을 표기하기 위한 용도이며, 또 하나는 quit 신호를 위한 것이다. 피보나치 함수는 select 문을 이용해 양쪽 channel 에서 대기한다. 라인 21 에서 시작되는 비동기 go 함수는 라인 23 에서 값들을 수신하기 위해 대기한 후, 그 값을 화면에 표시한다. 10번을 반복한 뒤 채널에는 quit 신호가 설정되며, 피보나치 함수는 멈춘다.
동시 실행 패턴, 예시 1
예제에서는 String 자료형으로 정의한 2개의 입력 channel인 input 1과 input2, 그리고 버퍼링 되지 않은 출력 channel인 c를 포함하고 있는 go 반복문인 fanIn을 생성하기 위해 select 문을 사용했다.
select 문은 fanIn이 양쪽 입력 channel을 동기식으로 수신하고, 준비된 것을 출력 channel로 중계하도록 한다. 각 입력 channel로부터 전송된 string 값을 받기 위해 동일한 임시 변수 이름을 사용해도 상관없다. 본 예시는 ‘Go에서의 동시성 패턴에 관한 롭 파크의 이야기 2012(Rob Pike's 2012 talk on Concurrency Patterns in Go)’에서 발췌했다.
동시 실행 패턴, 예시 2
본 예시는 실제로 구글이 하는 것과 유사한 인터넷의 병렬 검색을 구현한다. 우선 replicas …Search 는 함수에 대한 variadic 매개변수이며, Search 와 Result 모두 다른 곳에서 정의되어 있는 자료형이다.
호출자는 N 검색 서버 함수를 First 함수에 넘겨준다. First 함수는 반환값으로 channel c를 생성하고, i번째 서버를 조회할 수 있는 함수를 정의하고, 이를 searchReplica에 저장한다. 그런 뒤, First 함수는 모든 N서버에 대해 비동기식으로 searchReplica를 호출한 뒤, N 서버로부터 받은 첫 번째 결과값을 반환한다. 본 예시는 ‘Go에서의 동시성 패턴에 관한 롭 파크의 이야기 2012(Rob Pike's 2012 talk on Concurrency Patterns in Go)’에서 발췌했다.
패키지 http
Go 'net/http' 패키지는 HTTP 클라이언트와 서버 구현을 제공한다. 본 예시는 디렉토리/usr/share/doc 의 콘텐츠를 웹 클라이언트로 반환하는 단순한 웹 서버를 구현하고 있다. 고 플레이그라운드(Go Playground) 온라인 환경에서는 제대로 동작하지는 않지만, Mac 명령줄(command line)에서는 구동하며 'http://localhost:8080/:'를 요청하는 웹 브라우저에 다음과 같은 결과값을 순서대로 반환한다. bash/, ccid/, cups/, groff/, ntp/, postfix/
패키지 템플릿
Go html/template 패키지는 코드 주입에 안전한 HTML 결과물을 생성할 수 있도록 데이터 중심의 템플릿을 구현한다. html/template 패키지에 의해 추가된 회피(Escaping) 기능이 없었다면, 예제에서는 실행 가능한 자바스크립트(JavaScript) 문자열 Hello, "!"을 실행할 수 있었을 것이다.