티스토리 뷰

golang

Go Modules - Local Modules

주먹불끈 2019. 4. 10. 13:40

개요

 

1) Go Modules Wiki 일부를 세세히 들여다보자

2) Local Module 이라는 표현이 적절한지는 모르겠으나

Go Modules 기능을 통해 Local Path 있는 Module 들을 import 하고 사용 있도록 해보자

 

 

참고링크

 

- Golang Wiki: https://github.com/golang/go/wiki/Modules

- stackoverflow1: http://bit.ly/2VyG3Sr

- http://bit.ly/2VB69Er

 

(참고) Package Module

 

Module 개념이다.

관련이 있는 Go Package 들을 모아서 하나의 유닛처럼 버저닝 해주는 것이다.

사용된 각각의 Package 들의 정확한 버전정보들을 기록해 두기에 dependency 관리가 된다.

 

이번에는 Golang Wiki 다음 항목까지만을 따라가 보도록 한다.


 

 

Quick Start - Example

 

$ mkdir -p /tmp/scratchpad/hello
$ cd /tmp/scratchpad/hello

폴더를 만들고, 들어간다

$ go mod init github.com/you/hello

go: creating new go.mod: module github.com/you/hello

$go mod init <모듈명> 실행하면 go.mod 파일이 만들어진다.

생성된 파일을 열어보면 module <모듈명> 밖에 없다.

 

$ cat <<EOF > hello.go
package main

import (
    "fmt"
    "rsc.io/quote"
)

func main() {
    fmt.Println(quote.Hello())
}
EOF

왼쪽과 같이 hello.go 라는 파일을 작성한다음

$ go build
$ ./hello

Hello, world.

go build 실행하면 go.mod 바뀐다.

$ cat go.mod

module github.com/you/hello

require rsc.io/quote v1.5.2

바로 hello.go 파일에서 import package require 들어가있다.

 

Quick Start - Daily Workflow

 

일반적으로는 이렇게 것이다.

 

    • Add import statements to your .go code as needed.
    • Standard commands like go build or go test will automatically add new dependencies as needed to satisfy imports (updating go.mod and downloading the new dependencies).
    • When needed, more specific versions of dependencies can be chosen with commands such as go get foo@v1.2.3, go get foo@master, go get foo@e3702bed2, or by editing go.mod directly.

1) .go 사용하고픈 package import 해준다.

 

2) go build 또는 go test 먹여주면, 1) 에서 추가한 package dependency 들이 반영됨

- go.mod 업데이트 되고

- 추가한 dependency 다운로드 된다.

 

3)  사용하고픈 package 정확한 버전이 있다면

- go get 에서 명시하거나

- go.mod 직접 edit 하면 된다.

 

때때로 쓸만한 기능들은 다음과 같다.

 

    • go list -m all — View final versions that will be used in a build for all direct and indirect dependencies (details)

빌드시 사용된 module 들의 버전을 확인할 있음

 

The -m flag causes list to list modules instead of packages.

    • go list -u -m all — View available minor and patch upgrades for all direct and indirect dependencies (details)

package 들의 minor, patch 가능여부를 확인

 

The -u flag adds information about available upgrades. When the latest version of a given module is newer than the current one, list -u sets the Module's Update field to information about the newer module.

    • go get -u or go get -u=patch — Update all direct and indirect dependencies to latest minor or patch upgrades (details)

최신 버전으로 업데이트

 

The -u flag instructs get to use the network to update the named packages

and their dependencies. By default, get uses the network to check out

missing packages but does not use it to look for updates to existing packages.

    • go build ./... or go test ./... — Build or test all packages in the module when run from the module root directory (details)

 

    • go mod tidy — Prune any no-longer-needed dependencies from go.mod and add any dependencies needed for other combinations of OS, architecture, and build tags (details)

go.mod 에서 불필요한 것들을 잘라내고, 필요한 것들을 추가한다.

1) 이상 필요없는 dependency 들은 삭제

2) 다른 OS, Architecture, Build tag 등을 위해 필요한 것들을 추가

    • replace directive or gohack — Use a fork, local copy or exact version of a dependency (details)

 

    • go mod vendor — Optional step to create a vendor directory (details)

 

 

New Concepts - Modules

 

모듈은 관련한 패키지들을 모아놓은 것이고, 전체를 하나의 유닛으로 버전관리한다.

이를 통해 모듈에 필요한 패키지들의 정확한 버전을 있다.

 

여러 모듈을 하나의 repository 관리할 수도 있으나, 하나의 저장소에 하나의 모듈을 관리하는 것을 원칙으로 한다.

 

Repository, Module, Package 관계

 

1) Repository 하나 이상의 Go Module 가진다.

2) Module 하나 이상의 Go Package 가진다.

3) Package 하나의 directory 안에, 하나 이상의 Go source file 가진다.

 

버전명은 3부분으로 구성된다.

- 기준: https://semver.org/

- v(major).(minor).(patch)

 

New Concepts - go.mod

 

1) 모듈은 Go source file 들로 이루어진 트리구조의 디렉토리라 보면 되고

2) 트리의 root go.mod 있다.

 

가지 directive 있다. module, require, replace, exclude

exclude replace 현재의 module 대해서만 적용이 된다.

 

예시를 통해서 알아보자.

 

module github.com/my/thing

 

require (
    github.com/some/dependency v1.2.3
    github.com/another/dependency/v4 v4.0.0
)

go.mod 파일이다.

 

1) 모듈명은 github.com/my/thing 이다.

- 이때 module 사용되며 module path 정의한다.

 

2)  이때 import 되는 package 들은 module path (여기서는 github.com/my/thing)

- common prefix 공유한다.

- 둘의 조합으로 package import path 결정한다.


 

좀더 구체적 예를 들어보자.

 

1) 모듈을 만든다고 하자. 모듈명은 github.com/my/repo 이다.

 

2) 모듈은 개의 package 가지고 있다.

-  github.com/my/repo/foo

-  github.com/my/repo/bar

 

3) 경우에 왼쪽과 같은 디렉토리 구조를 가지게 된다.

 

4) 이제 누군가가 bar package import 하고 싶다면

- import "github.com/my/repo/bar" 라고 하면 된다.

 

When should I use the replace directive?

FAQ 항목의 일부만 추려내어 본다.

 

The replace directive allows you to supply another import path that might be another module located in VCS (GitHub or elsewhere), or on your local filesystem with a relative or absolute file path. The new import path from the replace directive is used without needing to update the import paths in the actual source code.

또다른 import path 제공할 있도록 해준다.

- GitHub 등의 인터넷 상의 path 이거나

- local file system 상의 path 이거나.

One sample use case is if you need to fix or investigate something in a dependency, you can have a local fork and add the something like the following in your top-level go.mod:

  • replace example.com/original/import/path => /your/forked/import/path

내가 fork package path redirect 해서 테스트 해볼 수도 있고

replace also allows the top-level module control over the exact version used for a dependency, such as:

  • replace example.com/some/dependency => example.com/some/dependency v1.2.3

좀더 정확한 버전을 명시하는데 수도 있다.

 

replace also can be used to inform the go tooling of the relative or absolute on-disk location of modules in a multi-module project, such as:

  • replace example.com/project/foo => ../foo

위에 언급했던대로 local file system 보낼 수도 있다.

In general, you have the option of specifying a version to the left of the => in a replace directive, but typically it is less sensitive to change if you omit that (e.g., as done in all of the replace examples above).

 

Note: for direct dependencies, a require directive is needed even when doing a replace. For example, if foo is a direct dependency, you cannot do replace foo => ../foo without a corresponding require for foo. (If you are not sure what version to use in the require directive, you can often use v0.0.0 such as require foo v0.0.0; see #26241).

direct dependency 경우에는

 

replace 쓸때에도 require 써줘야 한다.

버전을 모르겠을때는 v0.0.0 먹여주면 된다.

Can I work entirely outside of VCS on my local filesystem?

FAQ 항목의 일부만 추려내어 본다.

 

If you want to have multiple inter-related modules on your local disk that you want to edit at the same time, then replace directives are one approach.

Here is a sample go.mod that uses a replace with a relative path to point the hello module at the on-disk location of the goodbye module (without relying on any VCS):

여러 개의 관련있는 모듈들이 local file system 있을때에

replace 사용해볼 있겠다.

 

아래 예제를 보자.

module example.com/me/hello

 

require example.com/me/goodbye v0.0.0

replace example.com/me/goodbye => ../goodbye

hello 모듈의 go.mod 파일이다.

 

1) Go source file 에서는

- import "example.com/me/goodbye" 라고 되어 있었을 거고

2) 이걸 replace 통해 relative path ../goodbye 가리키게 한다.

 

As shown in this example, if outside of VCS you can use v0.0.0 as the version in the requiredirective. Note that as mentioned in the prior FAQ, the require directive is needed here. (replace example.com/me/goodbye => ../goodbye does not yet work without a corresponding require example.com/me/goodbye v0.0.0; this might change in the future with #26241).

1)  버전으로 v0.0.0 있다.

2) replace 만으로는 안되고 쌍이 되는 require 필요하다.

 

실전 예제

 

- 링크: http://bit.ly/2VyQUf9

 

1) /tmp/playground 라는 폴더가 있고

2) 서브 폴더로 hello, goodbye 있으며

3) 각각 go.mod hello.go, goodbye.go 있다.

hello 폴더의 go.mod 보면

 

이놈의 모듈명을 example.com/me/hello 라고 해둔걸 있다.

- hello.go package main 뒤에 코멘트로 // import "example.com/me/hello" 라고 해두고

$go mod init 치거나

- $go mod init example.com/me/hello 라고 명령하면 이렇게 생성된다.

 

그리고 require replace 이용하여

example.com/me/goodbye import 하기 위한 작업을 해두었다.

실제 hello.go 파일을 보면

 

import "example.com/me/goodbye:" 라고 import 하고 있다.

 

goodbye go.mod 에는 모듈명이 module example.com/me/goodbye 라고 되어 있다.

실제 실행결과는 왼쪽과 같다.


반응형
반응형
잡학툰 뱃지
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함