GOMODULE--Goのパッケージ管理

# Goのパッケージ管理
![go-lenguaje-programacion-google-blog-hostalia-hosting.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320164/709728cb-f955-9459-d0e5-8242e5911a8c.jpeg)

## 【2022/11】Go1.19について追記
`go get` はGo1.18から削除されました。どうしても従来のように `go get` でビルドとインストールを行いたい場合、GO111MODULE 環境変数を off にしてGOPATHモードにすることで可能です。

`go get`削除された経緯は`go mod tidy`で代用できるからです。Go1.16以降であれば`go install`使いましょう。:point_up_tone1:

## 本編

GOMODULEが誕生される前に `GOPATH` と `GOVENDOR`を使用してパッケージの管理をするのが一般的でした。

`GOPATH` : Go言語一度でも使用したことがあれば、お馴染みがあると思います、`GOROOT`と一緒に、Go言語の環境構築時にセットしてると思います。また、配下に `src`フォルダが存在することが必須とされています

`GOVENDOR`: パッケージ管理を専門フォルダー`vendor`に一任する、 `glide, dep,go dep...`などの管理ツールもあります

でも、どっちを使用しても、便利とは言えない

- GOPATH
    - 全てのプロジェクトは`src`フォルダに置かなければならない、すぐフォルダがパンパンになります

- GOVENDOR
    - ディレクトリに対しての依存性が厳しい、場合によって`vendor`の配下にまた`vendor`が存在します
   
# GOMODULE goモジュール

Go1.11バージョン以降追加された機能です。またバージョン上げてない方はバージョンアップしてください

公式の説明は以下になります [リンク](https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more)

```
Go 1.13には、Goモジュールのサポートが含まれています。モジュール対応モードは、現在のディレクトリまたはその親にgo.modファイルが見つかった場合にデフォルトでアクティブになります。

モジュールサポートを利用する最も簡単な方法は、リポジトリをチェックアウトし、そこにgo.modファイル（次のセクションで説明）を作成し、そのファイルツリー内からgoコマンドを実行することです。

より細かく制御するために、Go 1.13は一時的な環境変数GO111MODULEを引き続き尊重します。これは、off、on、またはauto（デフォルト）の3つの文字列値のいずれかに設定できます。GO111MODULE = onの場合、goコマンドではモジュールを使用する必要があり、GOPATHを参照することはありません。これを、モジュール対応または「モジュール対応モード」で実行されるコマンドと呼びます。GO111MODULE = offの場合、goコマンドはモジュールサポートを使用しません。代わりに、ベンダーのディレクトリとGOPATHを調べて依存関係を見つけます。これを「GOPATHモード」と呼びます。GO111MODULE = autoまたは未設定の場合、goコマンドは現在のディレクトリに基づいてモジュールサポートを有効または無効にします。モジュールのサポートは、現在のディレクトリにgo.modファイルが含まれる場合、またはgo.modファイルが含まれるディレクトリの下にある場合にのみ有効になります。

モジュール対応モードでは、GOPATHはビルド中のインポートの意味を定義しなくなりましたが、ダウンロードされた依存関係（GOPATH / pkg / mod）とインストールされたコマンド（GOBINが設定されていない場合はGOPATH / bin）を保存します。
```

では、早速使ってみます、まずgoの環境変数を確認します

```bash
$ go env
```

```bash
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\user\AppData\Local\go-build
set GOENV=C:\Users\user\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\user\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
```
下記のようにgomoduleの値は空になってます
それはどういう意味かというとと
`goのプロジェクトがGOPATHの配下に存在すれば=off,でなければ=on`

```
set GO111MODULE=
```
でもそのまましておくと、一部エラーを引き起こす可能性があります。
下記のコマンドを実行して修正しましょう

```
$ go env -w GO111MODULE=on
```
実行後、再度env情報確認すれば、下記のようにonになってるはずです

```
set GO111MODULE=on
```
# GOMODULE実際使ってみます

任意のディレクトリでフォルダを新規に作ってください

```bash
$ mkdir gomodtest && cd gomodtest
```
gomodをセット、名前を何にするのかは任意

```shell

$ go mod init gomodtest
```
実行後、 `go.mod`ファイルが作られたと思います、中身を見てみますと

```
module gomodtest

go 1.13
```
- プロジェクト名
- 使用してるgoのバージョン

が確認できるはずです、早速パッケージを `get` しましょう

```
$ go get -u go.uber.org/zap
```
終了後、また`go.mod `の中身をみてみましょう、先ほどgetしたパッケージ内容が記録されてることが確認できます。

```
module gomodtest

go 1.13

require (
	go.uber.org/atomic v1.5.1 // indirect
	go.uber.org/multierr v1.4.0 // indirect
	go.uber.org/zap v1.13.0 // indirect
	golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f // indirect
	golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f // indirect
)
```
また、同じディレクトリに`go.sum`ファイルが増えてると思います、中身を確認すると

```
省略
...
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
...
省略
```
パッケージのバージョンとそのhash値が入ってます、それは、パッケージが不正なカイゼンされないことが確保しますとの用途です

下記のコマンド実行すれば`go.sum`の内容を`go.mod`に同期できます

```
$ go mod tidy
```
goモジュール使用する場合、パッケージは下記のディレクトリに存在します

```
/gopath/pkg/mod/go.uber.org/zap@v1.13.0/field.go
```
#### 最後
インストールしたパッケージを使ってみましょう、`Uber`さんがオープンソースしたlog出力用のパッケージです
gomodtestディレクトリの配下でgoファイルを新規に作ります

```shell:

$ vim main.go
```

```go:gomodtest/main.go

package main

import "go.uber.org/zap"

func main(){ 
 logger, _ := zap.NewProduction()
 logger.Warn("warning test")
}
```
実行すれば、以下の出力が確認できます

```
{"level":"warn","ts":1574911209.375762,"caller":"gomodtest/main.go:7","msg":"warning test"}
```

# 既存プロダクトのGOMODULE使用

```bash

$ cd [とあるgomod使用していないgoプロジェクト] && go mod init [プロジェクト名]
```
その後、ディレクトリ内の全てのファイルをbuildします

```bash
$ go build ./...
```
以上、完了です

# 追記 
githubなどからソースをcloneして使用する場合、
GOMODULE使用してるプロダクトであれば、下記のコマンドでパッケージのインストール出来ます。

```
$ go mod tidy
```