Go의 라이브러리 구조

RepositoryModule로 구성. ModulePackage로 구성.

Repository

Repository는 소스코드를 저장할 VCS(Version Control System)이 존재하는 곳. 일반적인 Repository 정의와 동일.

Module

Module은 하나의 unit으로 버전이 매겨지고 배포되는 코드들을 말하며 Repository에 여러 개의 Module이 존재.

Go에서 Module은 전역적으로 유일한 Module path를 가진다. (ex. go.etcd.io/etcd/client/v3)

go mod init UNIQUE_MODULE_PATH # 이때 경로가 module path

Package

Module을 구성하는 요소. Module은 여러 개의 Package로 구성됨.


go.mod의 구조

module MODULE_PATH

go GO_VERSION

require (
    MODULE_PATH1
    MODULE_PATH2
)

require (
    MODULE_PATH3 // indirect
    MODULE_PATH4 // indirect
    MODULE_PATH5 // indirect
)

Module 이름

go mod init을 통해 정해진 module path로 작성됨.

Go 버전

실행을 위해 필요한 최소한의 go version. (실행하기 위해선 이 버전 이상을 사용해야 함.)

go directive의 버전이 설치된 go 버전보다 더 최신일 경우 toolchain directive 또는 GOTOOLCHAIN 환경 변수로 할 행동을 선택할 수 있음.

  • auto: 새로운 go 버전을 다운로드
  • local: 1.21 버전 이전으로 동작
  • 특정 버전: goGOVERSION으로 특정 버전 다운로드

require

이 모듈을 실행하기 위한 dependencies. indirect는 dependencies의 dependencies를 나타내고 특별한 기능은 없음.


Package 빌드

Import와 Export

Export된 상수, 변수, 함수, 타입을 import 가능. Export는 identifier의 첫 번째 문자를 대문자화 시킴으로써 가능.

Package 만들기 및 Import

package PACKAGE_NAME

import (
    "IMPORT_PATH1"
    "IMPORT_PATH2"
    "IMPORT_PATH3"
)
...

Import path는 module path + package path로 구성됨. Package를 담는 directory는 가급적 package 이름과 동일한게 좋지만 import 경로는 package 이름에 의해 결정.

Package 이름이 겹치는 경우

기본적으로 같은 이름의 변수, 타입, 함수가 선언되면 import된 package는 가려짐.
이를 피하기 위해 다음과 같이 overriding 사용.

import (
    pkg1 "AAA/PACKAGE1"
    "BBB/PACKAGE2"
)

Internal package

Package가 공유하고 싶지만 module 밖으로 expose하고 싶지 않을 경우 사용. Parent, sibling package에서만 해당 package 이용 가능. Package 이름으로 internal 사용.

package internal
...

Circular dependency

Go는 circular dependency를 허락하지 않음. (A -> B, B -> A) 최대한 circular dependency가 생기지 않도록 하고 생기는 경우 package를 하나로 결합.