참조: https://go.dev/doc/tutorial/call-module-code
개요
이번에는 2 개의 Go 모듈을 만들어 본다. 처음에는 다른 라이브러리나 어플리케이션에서 import 되도록 하는 모듈을 만들고, 그 다음에 이를 호출하는 호출 어플리케이션 모듈을 만든다.
호출되는 모듈 만들기
Go 코드는 package 로 그룹화되고, package 는 module 로 그룹화 된다. 모듈은 코드를 실행하는데 필요한 종속성과 Go 버전, 해당 코드가 필요한 모듈의 집합을 정의한다.
일반적으로 모듈에 기능을 추가하거나 개선하면 모듈의 새로운 버전을 배포한다. 만약 내가 작성한 모듈의 기능을 호출한 사용자가 있다면 해당 사용자는 갱신된 package 를 import 하고 운영에 배포하기 전에 새로운 버전을 test 할 수 있다.
greetings directory 를 생성하고 go mod init 명령어로 모듈을 초기화 한다. 이때 path 는 example.com/greetings 로 지정한다.
앞의글에서도 설명했지만 go mod init 명령어는 코드의 의존성들을 추적하는 go.mod 파일 생성한다. 지금은 go.mod 파일에 지정한 모듈 이름과 Go version 정보만 있을것이다. 하지만 의존성을 추가하면 go.mod 파일에는 코드가 의존하는 버전들이 나열된다.
greetings.go 파일을 생성하고 아래 코드를 복사한다. Go 에 대해 자세히 몰라도 다른 언어를 경험해보았다면 이름을 인자로 받아 출력한다고 예상할 수 있을것이다.
package greetings
import "fmt"
// Hello returns a greeting for the named person.
func Hello(name string) string {
// Return a greeting that embeds the name in a message.
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message
}
여기까지 greetings package 를 만들고 관련 함수를 작성하엿다.
Hello 는 함수이름이며, name string 에서 string 이 파라미터 타입이다. 그리고 ) string { 에서 string 은 반환형이다. Go 에서 함수이름을 대문자로 시작하면 외부 package 에서 호출할 수 있다. (java 로 치면 public 접근제어자에 해당한다.) 이것을 Go 에서는 exported 되었다고 표현한다.
Go 에서 := 연산자는 변수를 선언하고 초기화하는 과정을 간단하게 표현(shortcut)한 것이다.(:= 연산자 우측의 value 형으로 자료형이 결정된다.) 이를 shortcut 으로 표현하지 않고 원래대로 풀어쓰면 아래와 같다.
var message string
message = fmt.Sprintf("Hi, %v. Welcome!", name)
다른 모듈에서 모듈 호출
위에서 greetings 모듈을 만들었다. 이번에는 greetings 모듈의 Hello 함수를 호출하는 코드를 작성해보자.
호출자(caller) 를 작성하기 위해 hello directory 를 만들고 Go module 을 만든다. 이때에도 go.mod 파일 생성을 위해 go mod init 명령어를 수행한다. path 는 example.com/hello 로 준다.
go mod init example.com/hello
hello directory 하위에 hello.go 파일을 생성한다. 그리고 아래 내용을 복사한다.
package main
import (
"fmt"
"example.com/greetings"
)
func main() {
// Get a greeting message and print it.
message := greetings.Hello("Gladys")
fmt.Println(message)
}
위의 코드에서 한 일은 아래와 같다.
- main package 를 선언하였다. Go 에서 어플리케이션으로 실행되는 코드는 main package 에 있어야 한다.
- example.com/greetings 와 fmt package 를 import 했다. 이 두 package 를 import 했다는것은 해당 package 들 함수에 접근할 수 있다는것을 의미한다. example.com/greetings 를 import 하면 Hello 함수에 접근할 수 있으며, fmt 를 import 하면 text 의 입력과 출력을 다룰 수 있다.
example.com/hello 모듈을 내 local 의 example.com/greetings 모듈로 바라보도록 수정한다. 운영 환경에서는 Go tool 들이 찾아서 다운로드할 수 있도록 repository 에 해당 모듈을 배포하겠지만 지금까지는 아직 배포하지 않았기 때문에 내 local 의 example.com/greetings 를 찾을 수 있도록 조치를 취해야 한다.
이를 위해 go mod edit 명령어를 사용해서 local repository 를 바라보도록 해야 한다. hello directory 에서 아래 명령어를 수행한다.
go mod edit -replace example.com/greetings=../greetings
명령어를 직관적으로 해석하면 의존성을 local 로 바라보도록 변경해준다는 것을 알 수 있다. 이 명령어를 수행하고 나서 go.mod 파일을 열어보면 replace 키워드 부분이 추가된것을 알 수 있다.
replace example.com/greetings => ../greetings
go mod tidy 명령어를 통해 example.com/hello 모듈의 의존성을 동기화하여 코드에서는 필요하지만 모듈에 아직 추적되지 않은 종속성을 추가한다. 명령어를 수행하고 나면 go.mod 파일에 아래 내용이 추가된다.
require example.com/greetings v0.0.0-00010101000000-000000000000
이 명령어는 greetings directory 에서 local code 를 발견한 다음 require 지시자로 example.com/hello 가 example.com/greetings 를 필요로 함을 추가한다. 이 의존성은 hello.go 에서 greetings package 를 import 했을 때 생성된것이다. module path 뒤에 나오는 숫자는 일종의 임시-버전이다.
실제 배포된 module 을 참조하기 위해 go.mod 파일은 replace 지시자를 제거하고, 끝에 tag version 이 있는 require 지시자를 사용한다.
ex) require example.com/greetings v1.1.0
go run . 으로 실행해보면 hello.go 에서 greetings 모듈을 정상적으로 호출하는것을 알 수 있다.
go run .
Hi, Gladys. Welcome!
'Language > Go' 카테고리의 다른 글
Go - test (0) | 2021.11.28 |
---|---|
Go - multiple input 과 return (0) | 2021.11.28 |
Go - random 과 slice (0) | 2021.11.28 |
Go - Return 과 handle an error (0) | 2021.11.28 |
Go - hello world 와 external package (0) | 2021.11.28 |
댓글