2장 첫 번째 프로그램

전통적으로 어느 프로그래밍 언어에서도 맨 처음으로 작성하는 프로그램은 "Hello World" 프로그램이라 한다. 이 프로그램은 단순히 터미널에 Hello World를 출력하기만 한다. 그럼 Go를 이용해 이 프로그램을 작성해 보자.

먼저 프로그램이 저장될 폴더를 하나 만든다. 1장에서 사용한 설치 프로그램은 홈 디렉터리에 Go라는 폴더를 하나 만든다. ~/Go/src/golang-book/chapter2라는 폴더를 하나 만든다. (여기서 ~는 홈 디렉터리를 의미한다) 터미널에서는 다음 명령을 입력해 이 같은 작업을 할 수 있다.

mkdir Go/src/golang-book
mkdir Go/src/golang-book/chapter2

텍스트 편집기를 이용해 다음과 같은 내용을 입력한다.

package main

import "fmt"

// 이것은 주석이다

func main() {
    fmt.Println("Hello World")
}

파일의 내용을 위와 같이 작성한 후 앞에서 만든 폴더에 main.go라는 이름으로 저장한다. 새 터미널 창을 열고 다음과 같이 입력한다.

cd Go/src/golang-book/chapter2
go run main.go

그러면 터미널에 Hello World라고 나타나는 것을 볼 수 있을 것이다. go run 명령은 하나 이상의 파일명을 받아(공백으로 띄워서) 그것들을 임시 디렉터리에 실행 파일로 컴파일한 다음 해당 프로그램을 실행한다. Hello World가 출력되지 않는다면 프로그램 코드를 입력할 때 실수를 했을지도 모른다. Go 컴파일러는 어떤 줄에서 실수를 했는지 알려줄 것이다. 대부분의 컴파일러와 마찬가지로 Go 컴파일러는 굉장히 깐깐해서 실수를 절대 용납하지 않는다.

2.1 Go 프로그램을 읽는 법

이 프로그램을 좀 더 자세히 살펴보자. Go 프로그램은 위에서 아래로, 왼쪽에서 오른쪽으로 읽는다. (책을 읽을 때처럼) 첫 줄은 다음과 같다.

package main

이것은 "패키지 선언(package declaration)"으로 알려져 있다. 모든 Go 프로그램은 반드시 패키지 선언으로 시작해야 한다. 패키지는 Go 언어에서 코드를 조직화하고 재사용하는 수단이다. Go 프로그램에는 두 가지 유형이 있는데, 바로 실행 프로그램과 라이브러리다. 실행 가능한 애플리케이션은 터미널에서 바로 실행할 수 있는 종류의 프로그램이다. (윈도우에서는 파일명이 .exe로 끝난다.) 라이브러리는 다른 프로그램에서 사용할 수 있게 패키징된 코드의 모음이다. 라이브러리에 대해서는 나중에 더 자세히 살펴볼 것이며, 지금은 어떤 프로그램을 작성하든 이 줄을 입력해야 한다는 것만 알아두자.

다음 줄은 빈 줄이다. 컴퓨터는 특수 문자(또는 여러 개의 문자)로 줄바꿈을 나타낸다. 줄바꿈, 빈칸, 탭은 공백 문자로 알려져 있다(눈으로 볼 수 없기 때문에). Go에서는 공백에 관해서는 신경 쓰지 않지만, 우리는 공백을 이용해 프로그램을 더 읽기 쉽게 만든다. (이 줄을 제거할 수도 있는데, 그렇게 하더라도 프로그램은 정확히 같은 방식으로 동작할 것이다)

다음으로 아래와 같은 내용이 나온다.

import "fmt"

import 키워드는 다른 패키지에 포함된 코드를 이용할 때 쓴다. fmt 패키지(형식화[format]의 축약형)에는 입력과 출력에 대한 형식화가 구현돼 있다. 방금 패키지에 관해 배운 내용을 고려했을 때 fmt 패키지의 파일에는 어떤 내용이 들어 있으리라 생각하는가?

위의 fmt가 큰따옴표로 둘러싸여 있다는 점을 눈여겨보자. 이런 식으로 큰따옴표를 사용하는 것은 "문자열 리터럴"이라고 알려져 있으며, "수식(expression)"에 해당한다. Go에서 문자열은 길이가 정해진 문자(글자, 숫자, 기호 등)의 나열을 나타낸다. 문자열은 다음 장에서 더 자세히 설명하겠지만 지금 염두에 둬야 할 중요한 내용은 여는 " 문자 다음에는 결국 다른 " 문자가 나와야 하며, 두 따옴표 사이에 있는 내용이 문자열에 포함된다는 것이다. (" 문자 자체는 문자열의 일부가 아니다)

//로 시작하는 줄은 주석(comment)으로 알려져 있다. 주석은 Go 컴파일러가 무시하며, 여러분을 위해 존재하는 것이다(또는 프로그램의 소스 코드를 읽는 누군가를 위해). Go에서는 두 가지 유형의 주석을 지원한다. // 주석은 //와 줄 끝 사이에 텍스트는 모두 주석으로 간주하고, /* */ 주석은 두 * 사이의 내용은 모두 주석으로 간주한다. (그리고 여러 줄에 걸친 내용도 주석에 포함된다)

주석 다음으로 함수 선언을 볼 수 있다.

func main() {
    fmt.Println("Hello World")
}

함수(function)는 Go 프로그램의 기본 구성 요소다. 함수는 입력과 출력, 그리고 문장(순서대로 실행되는)이라고 하는 일련의 단계를 포함한다. 모든 함수는 func라는 키워드로 시작해 이어서 해당 함수의 이름(이 경우 main), 괄호로 둘러싸인 0개 이상의 "매개변수(parameter)", 반환형(선택 사항), 중괄호로 둘러싸인 "본문(body)"이 온다. 이 함수에는 매개변수가 없고, 아무것도 반환하지 않으며, 문장만 한 줄 담고 있다. main이라는 이름은 특별한데, 이 함수는 프로그램을 실행할 때 호출되는 함수이기 때문이다.

프로그램의 마지막 요소는 다음과 같다.

fmt.Println("Hello World")

이 문장은 세 가지 구성요소로 이뤄져 있다. 먼저 fmt 패키지 안에 포함된 Println라는 함수에 접근한다(fmt.Println에 해당하는 부분이며 PrintlnPrint Line을 의미한다). 그런 다음 Hello World가 담긴 새 문자열을 생성해서 해당 문자열을 첫 번째이자 유일한 인자로 함수를 호출*한다.

* 원서에서는 invoke라는 표현을 썼는데, 호출(call)이나 실행(execute)라는 표현을 쓰기도 한다. - 옮긴이

지금까지 새로운 용어가 너무 많이 나와서 약간 부담될지도 모르겠다. 때로는 프로그램을 크게 소리내어 읽는 것이 도움될 때가 있다. 방금 작성한 프로그램을 한번 읽어보면 다음과 같을 것이다.

새로운 실행 프로그램을 만드는데, 이 프로그램에서는 fmt 라이브러리를 참조하고 main이라는 함수 하나만 담고 있다. 해당 함수는 인자를 받지 않으며, 아무것도 반환하지 않고 다음과 같은 일만 한다. fmt 패키지 안에 담긴 Println 함수에 접근해 Hello World라는 문자열 하나를 인자로 사용해 해당 함수를 호출한다.

이 프로그램에서는 Println 함수에서 실제 작업을 수행한다. 터미널에서 다음과 같이 입력하면 Println 함수에 관해 좀 더 자세히 알 수 있다.

godoc fmt Println

그중에서도 다음과 같은 내용을 볼 수 있을 것이다.

Println은 피연산자에 대해 기본 형식을 이용해 형식화해서 표준 출력에 출력한다. 
연산자 사이에는 항상 빈칸이 추가되고 줄바꿈이 추가된다. 쓴 바이트 수와 쓰기 오류가 발생할 경우
오류를 반환한다.

Go는 문서화가 굉장히 잘 돼 있는 프로그래밍 언어지만 문서화된 내용은 프로그래밍 언어에 익숙하지 않을 경우 이해하기 어려울 수 있다. 그럼에도 godoc 명령은 굉장히 유용하며, 궁금한 사항이 있을 때마다 참고하에 좋은 자료다.

앞에서 다룬 함수로 되돌오면, 문서화된 내용에는 Println 함수가 입력한 내용을 표준 출력(현재 작업 중인 터미널의 출력을 가리키는 이름)으로 보낸다고 적혀 있다. 따라서 이 함수는 Hello World가 표시되게 한다.

다음 장에서는 타입에 관해 배움으로써 Go에서 Hello World 같은 것을 저장하고 표현하는 방법을 살펴본다.

연습 문제

  1. 공백이란 무엇인가?
  2. 주석이란 무엇인가? 주석을 작성하는 두 가지 방법은?
  3. 앞에서 작성한 프로그램은 package main으로 시작한다. fmt 패키지 안에 포함된 파일은 무엇으로 시작하겠는가?
  4. 앞에서는 fmt 패키지에 정의된 Println 함수를 사용했다. os 패키지에 포함된 Exit 함수를 사용하고 싶다면 어떻게 해야 하는가?
  5. 앞에서 작성한 프로그램을 수정해 Hello World를 출력하는 대신 Hello, my name is에 이어 여러분의 이름이 출력되게 만들어라.
이전다음 →