개요
이번 블로그 포스트에서는 Golang의 Package
(패키지)를 자세히 알아보고 사용하는 방법에 대해서 살펴보려고 합니다. 이 블로그 포스트에서 소개하는 코드는 다음 링크를 통해 확인하실 수 있습니다.
패키지
Golang에서 패키지는 코드를 묶는 기본 단위입니다. 따라서 모든 코드는 반드시 패키지로 묶어야 합니다.
또한 Golang으로 프로그램을 작성한다면, 반드시 main
패키지가 존재해야 하며, main
패키지안에 main
함수가 정의되어야 합니다. Golang에서는 이 main 패키지의 main 함수가 프로그램의 시작 위치가 됩니다.
main 패키지이외에 패키지들은 실행 시점(main 함수)을 포함하지 않은 패키지들로써, main 패키지의 보조 패키지로 동작하게 됩니다.
이런 모든 패키지를 가지고 있는 것이 모듈입니다. 모듈에 대해서는 아래에 링크를 참고하시기 바랍니다.
패키지 사용
그럼 패키지의 사용을 확인하기 위해 main.go
파일을 다음과 같이 수정합니다.
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println(rand.Int())
}
이 예제에서는 fmt
패키지와 math
패키지 하위의 rand
패키지를 가져왔으며, 화면에 숫자를 랜덤하게 표시하고 있습니다. 이렇게 작성한 코드를 실행하면, 다음과 같은 결과를 얻을 수 있습니다.
# go run main.
5577006791947779410
패키지 외부 공개
Golang에서는 패키지내 타입, 전역 변수, 상수, 함수, 메서드 등을 외부로 공개하여 다른 패키지에서 사용할 수 있습니다. 패키지에서 외부로 공개할 때에는 대문자로 시작하며, 외부로 공개하지 않을 때에는 소문자로 시작합니다.
패키지를 외부에 공개하고 공개된 패키지를 사용할 때에는 모듈을 사용해야 합니다. 모듈에 대한 자세한 내용은 아래에 링크를 참고하시기 바랍니다.
외부에 공개하는 패키지를 만들어보기 위해 greeting
폴더를 만들고 greeting.go
파일을 생성하고 다음과 같이 수정합니다.
package greeting
import "fmt"
const PI = 3.14
func PrintGreeting() {
print()
}
func print() {
fmt.Println("Hello, World!")
}
이렇게 수정하였다면, 다음 명령어를 사용하여 greeting
모듈을 생성합니다.
go mod init github.com/dev-yakuza/study-golang/package/greeting
이 greeting
패키지는 greeting
모듈을 통해 공유될 예정입니다. 이렇게 공유되는 greeting
패키지를 사용하는 main
패키지를 만들어 봅시다.
greeting
폴더와 같은 위치에 main
폴더를 생성하고 해당 폴더에 main.go
파일을 만들고 다음과 같이 수정합니다.
package main
import (
"fmt"
"github.com/dev-yakuza/study-golang/package/greeting"
)
func main() {
fmt.Println(greeting.PI)
greeting.PrintGreeting()
}
이제 다음 명령어를 사용하여 모듈을 생성합니다.
go mod init github.com/dev-yakuza/study-golang/package/main
모듈을 생성하였다면, 로컬에 존재하는 greeting
모듈을 사용하기 위해 다음 명령어를 실행합니다.
go mod edit -replace github.com/dev-yakuza/study-golang/package/greeting=../greeting
마지막으로 다음 명령어를 실행하여 모듈을 설정합니다.
go mod tidy
이렇게 만든 프로그램을 실행하면 다음과 같은 결과를 확인할 수 있습니다.
# go run main.go
3.14
Hello, World!
init 함수
패키지는 init
함수를 가질 수 있으며, 이 init
함수는 패키지가 import
될 때 한번 호출됩니다. 패키지의 init
함수는 패키지내의 전역 변수를 초기화할 때 사용합니다.
이를 확인하기 위해 greeting/greeting.go
파일을 다음과 같이 수정합니다.
package greeting
import "fmt"
const PI = 3.14
var globalVal = 0
func init() {
fmt.Println("init()", globalVal)
globalVal++
}
func PrintGreeting() {
print()
}
func print() {
fmt.Println("Hello, World!", globalVal)
}
그리고 main
폴더에서 다음 명령어를 실행하여 수정된 내용을 확인합니다.
go run main.go
프로그램이 실행되면 다음과 같은 결과를 확인할 수 있습니다.
init() 0
3.14
Hello, World! 1
별칭 패키지명
Golang에서는 이처럼 미리 만들어진 패키지들을 활용하여 프로그램을 작성하게 됩니다. 하지만, 모든 개발자가 약속하고 패키지를 제작하는 것이 아니기 때문에, 때로는 패키지명이 중복되는 경우가 있습니다.
import (
"text/template"
"html/template"
)
template.New("foo").Parse(`{{define "T"}}Hello{{end}}`)
template.New("foo").Parse(`{{define "T"}}Hello{{end}}`)
이처럼 중복된 패키지명을 사용해야하는 경우, 별칭 패키지명
(Alias Package Name)을 사용할 수 있습니다.
import (
htmlplate "html/template"
"text/template"
)
template.New("foo").Parse(`{{define "T"}}Hello{{end}}`)
htmlplate.New("foo").Parse(`{{define "T"}}Hello{{end}}`)
이를 확인하기 위해 아래와 같이 main.go
파일을 수정합니다.
package main
import (
"fmt"
htmlplate "html/template"
"text/template"
)
func main() {
fmt.Println(template.New("foo").Parse(`{{define "T"}}Hello{{end}}`))
fmt.Println(htmlplate.New("foo").Parse(`{{define "T"}}Hello{{end}}`))
}
이를 실행하면 다음과 같은 결과를 확인할 수 있습니다.
# go run main.go
&{foo 0xc00010e480 0xc00006c050 } <nil>
&{<nil> 0xc000104140 0xc00010e900 0xc00006c0a0} <nil>
빈칸 지시자
Golang에서는 패키지도 변수와 같이 선언하였다면 반드시 사용해야 합니다. 그렇지 않으면 컴파일 에러가 발생합니다. 하지만, 패키지를 직접 사용은 하지 않지만 import를 통해 init()
함수를 실행시켜 패키지를 초기화해야 하는 경우가 있습니다. 이때 별칭 패키지명
과 빈칸 지시자
(Blank identifier, _
)를 사용하여 에러를 해결할 수 있습니다.
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
패키지를 import하면 기본적으로 패키지 안에 있는 init()
함수가 호출되게 됩니다. 즉, 패키지를 import하여 init()
함수를 호출할 필요는 있지만, 다른 기능을 사용하지 않을 때, 위와 같이 별칭 패키지명과 빈칸 지시자를 활용합니다.
이를 확인하기 위해 init 함수의 예제에서 main.go
파일을 다음과 같이 수정합니다.
package main
import (
"fmt"
_ "github.com/dev-yakuza/study-golang/package/greeting"
)
func main() {
fmt.Println("Hello")
}
그리고 이를 실행하면 다음과 같은 결과를 확인할 수 있습니다.
# go run main.go
init() 0
Hello
import cycle
Golang에서 서로 다른 패키지가 서로 서로를 import하면 import가 계속 반복되므로 import cycle
에러가 발생합니다.
이를 확인하기 위해 greeting/greeting.go
파일을 생성한 후, 다음과 같이 수정합니다.
package greeting
import (
"fmt"
"github.com/dev-yakuza/study-golang/package/name"
)
func Print() {
fmt.Println("Hello, ", name.Name)
}
이제 다음 명령어를 실행하여 모듈을 생성합니다.
# cd greeting
go mod init github.com/dev-yakuza/study-golang/package/greeting
이제 import cycle
에러를 발생시키기 위해, greeting
폴더와 동일한 위치에 name/name.go
파일을 생성한 후, 다음과 같이 수정합니다.
package name
import (
"github.com/dev-yakuza/study-golang/package/greeting"
)
var Name = "John"
func print() {
greeting.Print()
}
이렇게 생성한 name
패키지도 다음 명령어를 실행하여 모듈을 생성합니다.
# cd name
go mod init github.com/dev-yakuza/study-golang/package/name
이렇게 만든 각각의 모듈에서 서로 참고하는 모듈을 연결하기 위해 다음 명령어를 실행합니다.
cd greeting
go mod edit -replace github.com/dev-yakuza/study-golang/package/name=../name
go mod tidy
cd ..
cd name
go mod edit -replace github.com/dev-yakuza/study-golang/package/greeting=../greeting
go mod tidy
이제 name.go
파일을 열고 greeting
패키지를 추가하는 곳을 살펴보면 다음과 같이 import cycle not allowed
에러가 발생하는 것을 확인할 수 있습니다.
완료
이것으로 Golang에서 패키지란 무엇이며 어떻게 사용하는지에 대해서 알아보았습니다. 이제 패키지를 제작하여 외부에 공유하거나, 외부로 공유된 패키지를 사용하여 프로그램을 제작해보시기 바랍니다.
제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!
앱 홍보
Deku
가 개발한 앱을 한번 사용해보세요.Deku
가 개발한 앱은 Flutter로 개발되었습니다.관심있으신 분들은 앱을 다운로드하여 사용해 주시면 정말 감사하겠습니다.