はじめてのGo Modules

初めてGoの開発案件にアサインされたのですが、前担当から引き継いだGoのバージョンが1.10なのに対して今回の開発では1.18だったので色々戸惑いました。
その際Go Modulesって何？となって調べたので備忘録。

# Go Modules 
- Go1.11以降で利用できる依存パッケージ管理ツール。
- go mod　init　[モジュールパス] と go mod tidyでgo.modとgo.sumを作成してソースコード内でimportに記載してる外部パッケージのダウンロードと依存関係の処理を行ってくれる。
    - Go1.10まではGOPATH モード (GOPATH mode)でコード管理を行なっており、コード管理とビルドをGOPATHで指定されたディレクトリ下で行っていた。Go1.11以降はモジュール対応モード (module-aware mode)を使用することで任意のディレクトリでコード管理とビルドが行えるようになった。


## 前提
- Go 1.18
- 環境変数GO111MODULEは　on　又は未指定
- MacOS Monterey 12.5.1

## ハンズオン
1. ##### 開発用ディレクトリでgo.modファイルの初期化を行う　（go mod init)
   ~~~zsh:zsh
    $ go mod init example.com/testgo
    
    //GitHubで公開するの場合
    $ go mod init github.com/(GitHubユーザ名)/(リポジトリ名)

  
    go: creating new go.mod: module example/testgo
    go: to add module requirements and sums:
            go mod tidy
    ~~~
    example.com/の部分は適宜変更する。
    このソースを外部モジュールとして使用しないのであれば入れなくてもよい。


    ちなみにこの時点ではgo.modの中身は以下の記載のみ。
    ~~~go:go.mod
    module example.com/testgo
        
    go 1.18
    ~~~

1. ##### コードを書く
   とりあえずテスト用として以下のコードを使用。
   AWS LambdaでHello Worldするサンプルコードです。
   ~~~go:main.go
    package main

    import (
        "github.com/aws/aws-lambda-go/lambda"
    )
    
    func hello() (string, error) {
        return "Hello ƛ!", nil
    }
    
    func main() {
        // Make the handler available for Remote Procedure Call by AWS Lambda
        lambda.Start(hello)
    }
    ~~~
1. ##### モジュールをインストールする(go mod tidy)
   ~~~zsh:zsh
   $ go mod tidy

   go: finding module for package github.com/aws/aws-lambda-go/lambda
   go: found github.com/aws/aws-lambda-go/lambda in github.com/aws/aws-lambda-go v1.34.1
   ~~~
    ソースコード内でimportに記載したパスからLambdaモジュールがインストールされ、go.modにLambdaモジュールの情報が追記されます。
    go.sumには依存先モジュールのチェックサム用のハッシュが記載されており、基本的に編集する必要はないです。

    ~~~go:go.mod
    module example.com/testgo

    go 1.19
    
    require github.com/aws/aws-lambda-go v1.34.1
    ~~~
1. ##### モジュールを追加してみる
   [logrus](https://pkg.go.dev/github.com/sirupsen/logrus)を追加します。
    ~~~go:main.go
    package main
    
    import (
    	"github.com/aws/aws-lambda-go/lambda"
    	"github.com/sirupsen/logrus" //add
    )
    
    func hello() (string, error) {
    	logrus.Info("Hello ƛ!") //add
    	return "Hello ƛ!", nil
    }
    
    func main() {
    	// Make the handler available for Remote Procedure Call by AWS Lambda
    	lambda.Start(hello)
    }
    ~~~
    go mod tidyで更新すると
    ~~~zsh:zsh
    $ go mod tidy

    go: finding module for package github.com/sirupsen/logrus
    go: found github.com/sirupsen/logrus in github.com/sirupsen/logrus v1.9.0
    ~~~
    ~~~go:go.mod
    module example.com/testgo
    
    go 1.18
    
    require (
    	github.com/aws/aws-lambda-go v1.34.1
    	github.com/sirupsen/logrus v1.9.0
    )
    
    require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect

    ~~~
    追加されてますね。
    ちなみにgo getでモジュールをインストールしてもgo.modに自動追加されます。
    こっちの方が使うケースが多いかもしれません。

1. ##### 動作確認
    ~~~zsh:zsh
    $ GOOS=linux GOARCH=amd64 go build -o testgo
    #lambda対応でzipにする
    $ zip testgo.zip testgo 
    ~~~
    AWSコンソール画面上での操作は省略。
    Lambdaへzip化したバイナリファイルをアップしてテストします。
    ![スクリーンショット 2022-09-01 2.20.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606710/a514199b-5e08-50c9-2c09-aed0f2e7136e.png)
成功しました。

## おまけ
##### depからの移行
私のケースでは前任者がdepを使用していた為Go Modulesへの移行が必要でした。
特に面倒な作業は必要なく、Gopkg.lockが存在する状態でgo mod initを行えばgo.modへ必要なモジュールを追加してくれたので楽ちんです。
詳細：[Migrating to Go Modules](https://go.dev/blog/migrating-to-go-modules)

## 参考
[Go Modules Reference](https://go.dev/ref/mod#go-mod-init) ~~まず公式ドキュメントを読もう！~~
[Goで扱うやつら（go.mod / go.sum / Makefile）って何なの？](https://qiita.com/ko-watanabe/items/606cfff04438fffd15d0)
[Go のモジュール管理【バージョン 1.17 改訂版】](https://zenn.dev/spiegel/articles/20210223-go-module-aware-mode#go-get-%E3%81%AF%E3%82%AA%E3%83%AF%E3%82%B3%E3%83%B3%EF%BC%9F)
[go mod完全に理解した](https://zenn.dev/optimisuke/articles/105feac3f8e726830f8c)