패키지
패키지는 Go언어에서 코드를 묶는 가장 큰 단위이다.
main 패키지
main패키지는 프로그램 시작점을 포함한 패키지이다. 운영체제는 프로그램을 실행하기 위해 프로그램을 메모리에 옮기고(이러한 작업을 load라고한다) 한줄한줄 시작하게 된다. 시작하는 점이 main()함수가 되는것이다.
이외 패키지
하나의 프로그램은 main패키지 이외 다른 패키지를 가질 수 있다.(장고가 프로젝트 디렉토리 이외에 여러가지 애플리케이션을 가질수 있는것과 비슷) 내장 패키지도 있지만, 오픈 소스로 공개된 여러 패키지와 유료 패키지 등 가져다가 사용할 수 있는 패키지도 많다. 패키지를 검색하려면 아래 두가지 방법을 사용하면 된다
- 표준 패키지 : https://pkg.go.dev/std
- 개발자들이 많이 사용하는 패키지(외장 패키지) : https://github.com/avelino/awesome-go
패키지 사용하기
패키지 사용을 위해서는 import 예약어를 사용하면 된다.
// 여러 패키지를 import 하는 경우
import (
"os"
"fmt"
)
// 하나의 패키지를 import 하는 경우
import "fmt"
외부에 노출할지의 여부는 "첫글자가 대문자인가 소문자인가"를 기준으로 구분한다 대문자이면 외부 노출을 하며 소문자로 시작하면 노출되지 않는다.
패키지 멤버 가져오기
패키지를 가져오려면 패키지명을 쓰고 . 연산자를 사용해 패키지 내 함수 구조체 등 멤버에 접근하면 된다.
fmt.Println("Hello world")
표준 출력도 결국 fmt라는 패키지의 Println함수에 접근한 것이다.
패키지 명이 겹치는 경우
import (
"fmt"
"text/template"
htemplate "html/template"
)
패키지 명이 겹치는 경우에는 별칭을 붙여 사용한다. 위 코드같은 경우 text/template과 html/template 모두 template라는 함수를 사용하게 된다. 하지만 html/template앞에 htemplate라는 별칭을 붙였다. 이런 경우 text/template은 그냥 template으로(template.~), html/template는 htemplate로 사용(htemplate.~)한다.
사용하지 않는 패키지 포함
Go언어에서는 변수를 선언하면 무조건 써야하고 패키지를 import하면 무조건 사용해야한다. 하지만 부가적인 효과만을 얻고자 한다면 밑줄(_)을 패키지 앞에 붙여주면 된다.
import (
"fmt"
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
외부패키지 활용해보기
외부패키지를 활용해 보자. 우선 아래와 같이 자신의 주 디렉토리 내에 다른 디렉토리(디렉토리가 즉 패키지가 된다)를 만들고 custompkg.go 파일을 만든다.
//custompkg.go
package usepkg
import (
"fmt"
)
func PrintCustom() {
fmt.Println("This is Custom Package!")
}
그 후 주 디렉토리에 uspkg.go를 만들고 아래와 같이 코드를 작성한다.
package main
import (
"awesomeProject/usepkg"
"fmt"
"github.com/guptarohit/asciigraph"
"github.com/tuckersGo/musthaveGo/ch16/expkg"
)
func main() {
usepkg.PrintCustom()
expkg.PrintSample()
data := []float64{3, 4, 5, 6, 9, 7, 5, 8, 5, 10, 2, 7, 2, 5, 6}
graph := asciigraph.Plot(data)
fmt.Println(graph)
}
선언부를 분석해보자
- awesomeProject/usepkg : 방금 만든 외부 패키지
- fmt : Go의 표준 입출력이 담긴 내장 패키지
- github.com/~~ : github.com에 있는 오픈소스 패키지들
첫번째 방법은 로컬 패키지를 만들어 불러오는 방식인 반면, 세번째 방법은 github.com에서 불러오는 독특한 방식으로 되어있다. 이렇게 불러오는 방식은 온라인에서 받아오는것이 아니다. 터미널에서
go mod tidy
를 입력해 Go모듈에 필요한 패키지를 찾아 다운로드 해주고 go.mod파일과 go.sum파일에 적어주게된다.
그리고 해당 깃허브 주소를 들어가 보면 실제로 Go 패키지가 존재하는것을 볼 수 있다.
https://github.com/guptarohit/asciigraph
실행을 해보면 아래와 같이 나온다
패키지 명과 패키지 외부 공개
위에서도 말했듯이 Go언어에서 첫번째 글자가 대문자인지 소문자인지에 따라 외부 공개될지가 결정된다고 하였다. 그렇기 때문에 우선 모든 문자를 소문자로 하는것이 좋다. 정말 외부로 공개를 해야하는 경우만 첫번째 글자로 대문자를 쓰는것이 좋다(대문자가 어떻게 보면 접근제어자 public의 역할을 하는것이다). 한번 패키지 외부 공개 / 공개 되지 않는 경우에 대한 예제를 살펴보자
package publicpkg
import "fmt"
const (
pi = 3.1415 // 공개되지 않수 상수
PI = 3.141516 // 공개되는 상수
)
var ScreenSize int = 1000 // 공개되는 변수
var screenHeight int = 100 // 공개되지 않는 변수
func PublicFunc() {
const MyConst = 100 // 공개되지않음 : 대문자로 시작하지만 함수 지역변수이므로 공개되지 않는개념
fmt.Println("This is a public Function ", MyConst)
}
func privateFunc() {
fmt.Println("This is private Function")
}
type Myint int // 공개되는 별칭
type myString string // 공개되지 않는 별칭타입
type MyStruct struct { // 공개되는 구조체
Age int // 공개되는 구조체 필드
name string // 공개되지 않는 구조체 필드
}
func (m MyStruct) PublicMethod() { // 공개되는 메솓,
fmt.Println("This is a public method")
}
func (m MyStruct) privateMethod() { // 공개되지 않는 메소드
fmt.Println("This is a private method")
}
type myPrivateStruct struct { // 공개되지 않는 구조체
Age int // 공개되지 않는 구조체 필드 : 대문자로 시작하더라도 포함된 구조체가 소문자로 시작해 외부로 노출되지 않는다.
name string // 공개되지 않는 구조체 필드
}
패키지가 초기화되는 과정
패키지를 초기화 하면 어떤 과정을 거칠까? 아래 과정대로 패키지가 초기화되게 된다.
- 패키지를 import하면 컴파일러는 패키지 내 전역 변수를 초기화한다
- init()함수가 있다면 호출해 패키지를 초기화 한다.
이 순서로 패키지가 초기화 되게 된다. 단 init()함수의 조건들이 있다.
- 매개변수 값이 없어야 한다
- 반환값이 없어야한다(void, 반환타입 무시)
패키지 초기화 과정을 볼 수 있는 예제 코드를 작성해 보았다
// awesomeProject/publicpkg/pblicpkg.go
package publicpkg
import "fmt"
var (
a = c + b // 이런 경우 b와 c가 초기화 된 후에 초기화된다.
b = f()
c = f()
d = 3
)
func init() {
d++
fmt.Println("init function : ", d)
}
func f() int {
d++
fmt.Println("f() d : ", d)
return d
}
func PrintD() {
fmt.Println("d : ", d)
}
//awesomeProject/usepkg.go ( main함수 )
package main
// 길기때문에 별칭을 붙여준 것이다.
import (
pkg "awesomeProject/publicpkg"
"fmt"
)
func main() {
fmt.Println("main function")
pkg.PrintD()
}
/*
f() d : 4 // 전역변수 b가 초기화 되는 부분
f() d : 5 // 전역변수 c가 초기화 되는 부분
// 여기까지 전역변수 초기화가 완료되었다
init function : 6
// init함수가 실행된다. init함수에도 d++가 있기 때문에 최종 6이 된다
main function
d : 6
// main함수
*/
'Language > GO' 카테고리의 다른 글
[GO] 함수 (0) | 2022.02.16 |
---|---|
[GO] fmt패키지를 이용한 텍스트 입출력하기 (0) | 2022.02.16 |
[GO] 변수 (0) | 2022.01.29 |
[GO] Hello GO (0) | 2022.01.28 |
[GO] GO 시작하기(feat. Apple Sillicon, 개발환경 구축, hello world출력) (0) | 2022.01.28 |