Go 1.11 Modulesの機能で取得した自前以外のモジュールは、どこにあるのか？

# お題
表題について確認する。主に以下の人が対象。
★今まで「[glide](https://github.com/Masterminds/glide)」や「[dep](https://github.com/golang/dep)」を使ってて、Go1.11でModulesを使い始めたものの違いに戸惑っている人。

これまでの「glide」や「dep」といったVendoring方式のツールがどんなだったかは下記参照。
[Goとvendoring](https://qiita.com/sky0621/items/499a249dd64f8fe2e39a)

Go 1.11 における Modules の概念については以下に載っている。
https://github.com/golang/go/wiki/Modules#go-111-modules

上記の冒頭文によると、
Go 1.11 において Modules は、あくまで実験的に導入したものである。
フィードバックを踏まえ、Go 1.13 で完成する。
下位互換は持たせるので Go1.11 及び Go 1.12 で作られた Module が Go 1.13 で使えなくなるということは無い。
とのこと。
プロダクションレベルで導入すべきかどうかは、判断の分かれるところだろう。

ちなみに上記のWikiから、主にチュートリアル部分を抜粋して試した記事が下記。
[Go 1.11 Modules](https://qiita.com/sky0621/items/9af758c7df5403caa991)

今回は、表題についての確認。

# 開発環境
### # OS
```
$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"
```

### # Docker
```
$ sudo docker version
Client:
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.4
 Git commit:        6247962
 Built:             Tue Feb 26 23:52:23 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.4
  Git commit:       6247962
  Built:            Wed Feb 13 00:24:14 2019
  OS/Arch:          linux/amd64
  Experimental:     false
```

### # Golang
```
$ go version
go version go1.11.4 linux/amd64
```

# 実践

自前端末の環境に依存しないよう、dockerhubの公式イメージを使う。

## ■ Go 1.11 の公式イメージを取得

### docker login

[docker login](https://docs.docker.com/engine/reference/commandline/login/)する。
【参考】
http://docs.docker.jp/docker-hub/accounts.html

```
$ sudo docker login
　〜〜〜
Login Succeeded
```

### docker search

【参考】
https://hub.docker.com/_/golang

```
$ sudo docker search golang
NAME                              DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
golang                            Go (golang) is a general purpose, higher-lev…   2614                [OK]                
　〜〜〜
```

### docker pull

```
$ sudo docker pull golang:1.11
1.11: Pulling from library/golang
　〜〜〜
Status: Downloaded newer image for golang:1.11
```

```
$ sudo docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
golang                   1.11                28daaf3edbdb        2 weeks ago         756MB
```

### docker exec

```
$ sudo docker run -it golang:1.11 
root@3c5e824d4a2d:/go# 
```

## ■ 適当なWebAPIを実装

前段で `docker exec` した状態からの作業。

### `GOPATH`外にソース置き場を作成

```
root@3c5e824d4a2d:/go# pwd
/go
root@3c5e824d4a2d:
root@3c5e824d4a2d:/go# env | grep GOPATH
GOPATH=/go
root@3c5e824d4a2d:
root@3c5e824d4a2d:/go# mkdir /usr/local/src/gowork
root@3c5e824d4a2d:/go# cd /usr/local/src/gowork/
```

### `GOPATH`外のソース置き場に自前以外のモジュールを使うWebAPIを実装

```
root@3c5e824d4a2d:/usr/local/src/gowork# cat <<EOF > main.go
> package main
> 
> import (
> "net/http"
> 
> "github.com/labstack/echo"
> )
> 
> func main() {
> e := echo.New()
> e.GET("/item", func(c echo.Context) error {
> return c.JSON(http.StatusOK, "OK")
> })
> e.Logger.Fatal(e.Start(":8080"))
> }
> 
> EOF
root@3c5e824d4a2d:/usr/local/src/gowork# 
root@3c5e824d4a2d:/usr/local/src/gowork# cat main.go 
package main

import (
"net/http"

"github.com/labstack/echo"
)

func main() {
e := echo.New()
e.GET("/item", func(c echo.Context) error {
return c.JSON(http.StatusOK, "OK")
})
e.Logger.Fatal(e.Start(":8080"))
}

root@3c5e824d4a2d:/usr/local/src/gowork# 
```

### Go Module初期化

```
root@3c5e824d4a2d:/usr/local/src/gowork# go mod init gowork
go: creating new go.mod: module gowork
root@3c5e824d4a2d:/usr/local/src/gowork# 
root@3c5e824d4a2d:/usr/local/src/gowork# cat go.mod
module gowork
```

### Webアプリの起動確認

起動時にソースの内容を元に、必要なモジュールをダウンロードする。

```
root@3c5e824d4a2d:/usr/local/src/gowork# go run main.go
go: finding github.com/labstack/echo v3.3.10+incompatible
go: downloading github.com/labstack/echo v3.3.10+incompatible
go: finding github.com/labstack/gommon/color latest
　　　〜〜〜　省略　〜〜〜
go: finding github.com/valyala/bytebufferpool v1.0.0
go: downloading golang.org/x/sys v0.0.0-20190412213103-97732733099d
go: downloading github.com/valyala/bytebufferpool v1.0.0

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:8080
```

### Webアプリ起動後の`go.mod`確認

Webアプリ起動時にダウンロードしたモジュールをバージョンとともに`require`として管理。

```
root@3c5e824d4a2d:/usr/local/src/gowork# cat go.mod 
module gowork

require (
	github.com/labstack/echo v3.3.10+incompatible // indirect
	github.com/labstack/gommon v0.2.8 // indirect
	github.com/mattn/go-colorable v0.1.1 // indirect
	github.com/mattn/go-isatty v0.0.7 // indirect
	github.com/valyala/fasttemplate v1.0.1 // indirect
	golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 // indirect
)
```

## ■ Go 1.11 Modulesの機能で取得した自前以外のモジュール

WebAPI実装ソース及び`go.mod`置き場には、自前以外のモジュールは存在しない。
「[glide](https://github.com/Masterminds/glide)」や「[dep](https://github.com/golang/dep)」であれば `vendor` ディレクトリがあって、その下に自前以外のモジュールのソースが置かれていたのだけど。

```
root@3c5e824d4a2d:/usr/local/src/gowork# ls -l
total 12
-rw-r--r-- 1 root staff  350 Apr 28 05:00 go.mod
-rw-r--r-- 1 root staff 2273 Apr 28 05:00 go.sum
-rw-r--r-- 1 root staff  213 Apr 28 04:59 main.go
```

となると、あとは、`GOPATH`の配下だろうね。

```
root@3c5e824d4a2d:/usr/local/src/gowork# env | grep GOPATH
GOPATH=/go
root@3c5e824d4a2d:/usr/local/src/gowork# 
root@3c5e824d4a2d:/usr/local/src/gowork# ls -l /go/    
total 12
drwxrwxrwx 2 root root 4096 Apr 12 22:23 bin
drwxr-xr-x 3 root root 4096 Apr 28 05:00 pkg
drwxrwxrwx 2 root root 4096 Apr 12 22:23 src
root@3c5e824d4a2d:/usr/local/src/gowork# 
root@3c5e824d4a2d:/usr/local/src/gowork# ls -l /go/bin/
total 0
root@3c5e824d4a2d:/usr/local/src/gowork# 
root@3c5e824d4a2d:/usr/local/src/gowork# ls -l /go/src/
total 0
```

`GOPATH/bin`と`GOPATH/src`は空。

```
root@3c5e824d4a2d:/usr/local/src/gowork# ls -l /go/pkg/
total 4
drwxr-xr-x 5 root root 4096 Apr 28 05:00 mod
root@3c5e824d4a2d:/usr/local/src/gowork# 
root@3c5e824d4a2d:/usr/local/src/gowork# ls -l /go/pkg/mod/
total 12
drwxr-xr-x 4 root root 4096 Apr 28 05:00 cache
drwxr-xr-x 5 root root 4096 Apr 28 05:00 github.com
drwxr-xr-x 3 root root 4096 Apr 28 05:00 golang.org
root@3c5e824d4a2d:/usr/local/src/gowork# 
root@3c5e824d4a2d:/usr/local/src/gowork# ls -l /go/pkg/mod/github.com/
total 12
drwxr-xr-x 4 root root 4096 Apr 28 05:00 labstack
drwxr-xr-x 4 root root 4096 Apr 28 05:00 mattn
drwxr-xr-x 4 root root 4096 Apr 28 05:00 valyala
```

うん。ここっぽいね。`GOPATH/pkg`
今回のGoソースで使っている `labstack/echo` を確認してみる。

```
root@3c5e824d4a2d:/usr/local/src/gowork# ls -l /go/pkg/mod/github.com/labstack/
total 8
dr-xr-xr-x 5 root root 4096 Apr 28 05:00 echo@v3.3.10+incompatible
dr-xr-xr-x 7 root root 4096 Apr 28 05:00 gommon@v0.2.8
root@3c5e824d4a2d:/usr/local/src/gowork# 
root@3c5e824d4a2d:/usr/local/src/gowork# ls -l /go/pkg/mod/github.com/labstack/echo\@v3.3.10+incompatible/
total 180
-r--r--r-- 1 root root  1075 Apr 28 05:00 LICENSE
　　〜〜〜　省略　〜〜〜
-r--r--r-- 1 root root  8265 Apr 28 05:00 bind.go
-r--r--r-- 1 root root 10848 Apr 28 05:00 bind_test.go
　　〜〜〜　省略　〜〜〜
-r--r--r-- 1 root root  8831 Apr 28 05:00 router.go
-r--r--r-- 1 root root 29962 Apr 28 05:00 router_test.go
```

バージョン指定付きでディレクトリが出来ていて、その中にはソースが展開されている。
ここであらためて、`go.mod` の中身を確認。

```
root@3c5e824d4a2d:/usr/local/src/gowork# cat go.mod 
module gowork

require (
	github.com/labstack/echo v3.3.10+incompatible // indirect
　　　　　　〜〜〜　省略　〜〜〜
)
```

このへんの記載とディレクトリに付与されたバージョンが連動している。
`GOPATH/pkg`の下にソースが展開されるとなると、複数のアプリが同じモジュールを使う時にそれぞれのアプリで使うバージョンが違ったりしておかしなことになるのではと思ったけど、こうしてバージョン付きのディレクトリ名にすることで複数バージョンを共存できるようにしているのだね。

# 備忘録
今回は`go run`を実行した時に`go.mod`に依存モジュールが`require`として追加されたけど、`go build`や`go test`実行時も同じらしい。
https://github.com/golang/go/wiki/Modules#daily-workflow