go run main.goを実行の際、各パッケージダウンロードに時間がかかりすぎる際の対処法

# 概要

本日は、ローカルで`Go`のファイルを実行した際に立ち上がりに時間がかかっており、

それを効率化する方法を見つけましたので共有したいと思います。

# 環境

今回もDockerを利用したいと思います。

```dockerfile
FROM golang:1.20-alpine3.16
ENV ROOT /app \
    TZ Asia/Tokyo
WORKDIR ${ROOT}
RUN apk update && apk add --no-cache git
COPY go.mod go.sum ./
RUN go mod download
COPY . .
EXPOSE 8080
CMD ["go", "run", "main.go"]
```

```docker-compose.yml
version: '3.8'
services:
  db:
    image: mysql:8.0
    container_name: mysql
    env_file:
      - .env
    environment:
      MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
      MYSQL_DATABASE: $DB_NAME
      MYSQL_USER: $DB_USER
      MYSQL_PASSWORD: $DB_PASSWORD
    volumes:
      - ./mysql:/var/lib/mysql
    ports:
      - 3306:3306

  api:
    build: .
    container_name: api
    working_dir: /app
    env_file:
      - .env
    environment:
      APP_ENV: $APP_ENV
      TZ: "Asia/Tokyo"
    volumes:
      - .:/app
    ports:
      - 8080:8080
    depends_on:
      - db
```

# 問題

ローカルで開発している際に、ファイルを`go run ファイル名`で実行することがよくあると思います。

その際に下記にように**ソースからパッケージを都度ダウンロード**するため、実行に時間がかかっていました。

```sh
$ docker compose run --rm api go run main.go
[+] Running 1/0
 ⠿ Container mysql  Running                                                                                                                                                  0.0s
go: downloading github.com/sirupsen/logrus v1.9.0
go: downloading gorm.io/driver/mysql v1.4.6
go: downloading gorm.io/gorm v1.24.5
go: downloading github.com/gin-gonic/gin v1.8.2
go: downloading github.com/go-sql-driver/mysql v1.7.0
go: downloading golang.org/x/sys v0.3.0
go: downloading github.com/jinzhu/now v1.1.5
go: downloading github.com/jinzhu/inflection v1.0.0
go: downloading github.com/gin-contrib/sse v0.1.0
go: downloading github.com/mattn/go-isatty v0.0.16
go: downloading golang.org/x/net v0.4.0
go: downloading github.com/go-playground/validator/v10 v10.11.1
go: downloading github.com/pelletier/go-toml/v2 v2.0.6
go: downloading github.com/ugorji/go/codec v1.2.7
go: downloading google.golang.org/protobuf v1.28.1
go: downloading gopkg.in/yaml.v2 v2.4.0
go: downloading github.com/go-playground/universal-translator v0.18.0
go: downloading github.com/leodido/go-urn v1.2.1
go: downloading golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
go: downloading golang.org/x/text v0.5.0
go: downloading github.com/go-playground/locales v0.14.0
```

これでは**外部パッケージが増えれば増えるほど実行するのに時間がかかってしまいます**。

# 対処法

何か良い方法はないかと模索したところ、`go mod vendor`というコマンドを見つけました。

公式ドキュメントには上記コマンドについて、下記のように記載されています。

> The go mod vendor command constructs a directory named vendor in the main module’s root directory that contains copies of all packages needed to support builds and tests of packages in the main module.
...省略
When vendoring is enabled, the go command will load packages from the vendor directory instead of downloading modules from their sources into the module cache and using packages those downloaded copies.



日本語訳

> go mod vendorコマンドは、メインモジュールのルートディレクトリにvendorというディレクトリを作成し、そこにメインモジュール内のパッケージのビルドとテストをサポートするために必要なすべてのパッケージのコピーを格納します。
...省略
vendoring が有効な場合、goコマンドはモジュールをソースからモジュールキャッシュにダウンロードし、それらのダウンロードしたコピーを使用する代わりに、ベンダディレクトリからパッケージをロードします。

つまり実行時にパッケージをソースからダウンロードを行うのではなく、

`vendor`ディレクトリにキャッシュされたパッケージをロードし利用するということです。

よって都度ソースからダウンロードをしなくてよくなるので実行する際の時間がかなり短縮されます！

## 注意点

`vendor`ディレクトリは必要なパッケージを格納していますが、

新たにパッケージを追加した際はその都度`go mod vendor`コマンドを実行しないと

追加したパッケージが`vendor`ディレクトリに格納されないので注意です。

# まとめ

いかがだったでしょうか。

ローカルで開発する際は`go mod vendor`コマンドを利用することで

ファイルの実行時間を短縮することができますので是非皆さんも試してみてください。

最後まで読んでいただきありがとうございました！