컬렉션을 시작으로 인터페이스까지 코드의 효율성, 재사용을 위해 끝없이 묶는(모듈화) 연습을 했다. 변수들을 묶은 컬렉션, 객체 정보를 묶은 메소드, 기능을 묶은 함수, 메소드를 묶은 인터페이스들을 학습하면서 더 이상 없다고 생각했지만 이 모든 것을 묶은 '패키지'가 있다. 이렇게 한 파일로 작성된 패키지인 컴포넌트는 코드의 모듈화, 코드의 재사용을 가능하게 한다. 이미 우리는 코드 상단에 import "fmt" 라고 습관적으로 입력하면서 수 없이 써왔다. 이것은 우리가 기능을 만들고 구현하지 않아도 누군가 만들어놓은 코드를 재사용한다는 것을 의미한다.
패키지는 두 종류가 있다. 바로 main 패키지와 그 외 패키지이다. main 패키지를 제외한 모든 패키지는 개발자가 직접 작성하든 Go언어에서 제공하는 패키지든 똑같이 취급된다. 반면에, main 패키지는 컴파일러에 의해 특별히 인식된다. 컴파일러는 main패키지를 공유 패키지(라이브러리)가 아닌 실행(executable) 프로그램으로 만든다. 자연스럽게 main 패키지 안에 main() 함수는 프로그램의 시작점(Entry point)이자 종료점이 된다. 따라서 패키지를 고융 라이브러리로 만들 때에는 main 패키지나 main 함수를 사용하면 안된다.
패키지 만들기
이미 Go언어는 강력한 내장 라이브러리가 있기 때문에 필요에 따라 얼마든지 import해서 사용할 수 있다. 또한 프로그램을 개발할 때 개발자가 직접 필요한 기능을 구현한 패키지를 만들고 여러 파일들 사이에서 import해서 쓸 수 있다. 이렇게 패키지를 통해 코드를 모듈화하고 코드의 재사용을 하는 것은 프로그램의 질적인 측면에서 굉장히 중요하다. 따라서 패키지를 사용해 작은 단위의 컴포넌트를 작성하고, 패키지들을 활용해 프로그램을 작성하는 것이 개발자의 능력이고 권장 사항이다. 우선 '시작하기에 앞서' 챕터에 '실습 환경 구축 - 구름IDE' 강의를 보면 구름IDE를 통해 실제 프로젝트 작성 홤녀과 작업 환경 구축에 대해 학습했다 구름IDE를 이용하면 따로 환경 변수를 설정하지 않고 컨테이너박스를 생성하는 것만으로도 작업 환경이 구축되기 때문에 적극 사용을 권장한다.
아래는 아무것도 하지 않고 Go 컨테이너를 생성했을 때 모습이다.
원래 Go언어는 GOPATH 환경변수에 설정한 경로를 통해 프로그램을 실행(컴파일)한다. 구름 IDE는 컨테이너 생성과 동시에 GOPATH에 자동으로 작업 공간 경로가 설정된다. 이는 하단 터미널에 go env 를 입력해보면 알 수 있다.
참고로 위 그림을 보면 GOROOT라는 것이 있는데 이 환경변수는 Go가 설치된 경로를 나타내면며, 표준패키지들이 있는 곳이다. (/pkg)
우리가 확인해야 할 것은 GOPATH이다. 위 그림에 GOPATH는 'workspace/go_package'로 자동 설정되어 있다. 'go_package'는 컨테이너를 생성할 때 만든 컨테이너 이름이다. 패키지는 GOPATH로 설정된 경로의 'src' 폴더에 만들어야한다. 패키지 생성은 패키지와 같은 이름의 폴더를 만들고 그 안에 Go파일을 만드는 것이다.(main 패키지 제외) 아래 그림을 보면 쉽게 알 수 있다.
패키지를 만들 때, src 폴더 안에 패키지 이름의 디렉터리를 만들면 된다. go 파일은 해당 디렉터리 안에 생성하고 작성한다. 예를 들어, 위 그림과 같이 연산을 하는 패키지를 만들 때 패키지 이름을 cal로 만들고 그 안에 특별히 덧셈을 하는 sum.go라는 파일을 생성한다. 아래는 두 수를 더하는 함수만 있는 cal 패키지를 작성한 예시와 main() 함수에서 cal 패키지를 import 한 예시이다.
그리고 터미널에서 경로를 src로 이동 후에(main.go가 있는 디렉터리) go run main.go 를 입력하면 프로그램이 실행된다.
여기서 눈 여겨 봐야할 점이 있다. 바로 함수 이름의 첫 글자이다.
- 첫 글자를 소문자로 지정하면 패키지 안에서만 사용할 수 있다.
- 첫 글자를 대문자로 지정하면 외부에서 사용할 수 있다. 위 예시가 그렇다.
다양한 패키지를 만들고 여러 파일 사이에서 사용하는 법을 학습했다.
그리고 여러 패키지를 import 하는 방법은 이미 다 알 것이라고 생각한다. 그래도 다시 한 번 짚고 넘어가자.
아래 예시와 같이 여러 패키지를 동시에 import할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import "fmt"
import "runtime"
import "time"
import "math/rand"
or
import (
"fmt"
"runtime"
"time"
"math/rand"
)
|
cs |
전역 패키지 사용하기
전역 패키지 선언은 특별하게 사용하지 않아도 되는 용법이기 때문에 지금까지 사용하지 않았다. 전역 패키지는 import할 때 패키지 이름 앞에 '.'(점)을 입력하면 선언된다. 이는 처럼 앞에 패키지 이름을 입력하는 것이 아니라 를 생략하고 와 같이 사용할 수 있다. 이는 함수, 변수, 상수에 동일하게 적용된다.
1
2
3
4
5
6
7
|
package main
import . "fmt"
func main() {
Println("Hello, Goorm!")
}
|
cs |
패키지 별칭
함수나 변수는 type문을 이용해 사용자 지정 형식으로 사용할 수 있다. 패키지도 아래와 같이 패키지 앞에 사용자 지정 이름을 붙여 사용하는 똑같은 용법이 있다. 이는 특히 Go언어에서 제공하는 패키지와 개발자가 직접 만든 패키지의 이름이 겹칠 때, 혹은 다른 사람이 만든 패키지와 이름이 겹칠 때 유용하게 사용할 수 있다.
그리고 Go언어는 사용하지 않는 변수에 대해 굉장히 철저하다고 했다. 만약 선언만 해놓고 사용하지 않으면 런타임 에러가 발생한다. 패키지도 똑같이 import만 하고 사용하지 않으면 에러가 발생한다. 이때 패키지 이름 앞에 '_'(언더바)를 입력하면 컴파일 에러가 발생하지 않는다. 이 기능은 디버깅할 때 주석을 하지 않고도 유용하게 사용할 수 있다.
아래 두 용법에 관한 예시 코드를 확인해보자.
1
2
3
4
5
6
7
8
9
10
|
package main
import (
f "fmt"
_ "runtime"
)
func main() {
f.Println("Hello, Goorm!")
}
|
cs |
'Go Language' 카테고리의 다른 글
[Go] #21-6 채널(Channel) - 채널 select (1) | 2023.01.18 |
---|---|
[Go] #21-5 채널(Channel) - 송신 전용, 수신 전용 채널 (0) | 2023.01.18 |
[Go] #21-4 채널(Channel) - 채널 닫기 (0) | 2023.01.18 |
[Go] #21-3 채널(Channel) - 동기 채널 (0) | 2023.01.18 |
[Go] #21-2 채널(Channel) - 비동기 채널과 버퍼 (0) | 2023.01.18 |