🦊

AWS SAMにGo言語で取り組む際のディレクトリ構成

2 min read

要約

  • SAMで複数のLambda関数を作りたいが、その中で使う自作パッケージは共通化したいときに、どのようなディレクトリ構成にしておけば良いか、調べた&試した結果を残します。
  • またgo.modはどこに置いて、各.goファイルから自作パッケージを参照するにはどうしたら良いのかについてもまとめます。
  • 以下のフォルダ構成が良いのかな、という結論に至りました。
project.root/
├─ go.mod
├─ go.sum
├─ cmd/
│  ├─ SAM_project1/
│  │  ├─ lambda1/
│  │  │  ├─ main.go
│  │  │
│  │  ├─ lambda2/
│  │
│  ├─ SAM_project2/
│
├─ pkg/
   ├─ package1/
   ├─ package2/

はじめに

  • 趣味でAWSを触り始め早一ヶ月、SAM(Serverless Application Model)を使って、ちまちまとLambdaを作っていました。
  • 開発規模が徐々に大きくなってきたところで、自作パッケージが循環参照に陥る等、見切り発車でディレクトリ構成を考えていたツケが回ってきました。こりゃいかんということでリファクタリングを始めたところで、「あれ、そもそもGo言語のディレクトリ構造とか、モジュール管理(go.mod)はどうするべきなんだっけ…?」と悩んでしまいました。

やりたいこと

  • 複数のLambdaで繰り返し使用する関数はパッケージにまとめて再利用したい。
  • 1つのSAM Projectの中で複数のLambdaを置きたい。
  • SAM Projectを複数持ちたい(用途毎に切り分けておきたい)。ただしパッケージは共通で使いたい。

要は、1つのプロジェクト内で、共通パッケージを持つ複数のアプリケーションを開発するケースと同じです。

何が私を迷わせたか

  • sam initでAWSテンプレートを使用すると下記のフォルダ構成が生成されると思います。この時、1つのLambda関数に相当するhello-worldディレクトリ内にgo.modが置かれているので、「あれ?Lambda関数毎に用意しておかないといけないのかな?」と考えてしまいました。
SAM-Root
│  Makefile
│  README.md
│  samconfig.toml
│  template.yaml
│
└─hello-world
        go.mod
        go.sum
        main.go
        main_test.go

しかしgo.modはプロジェクトのモジュール環境を整えるものなので、もっと大きな括りで用意すれば良いことが、四苦八苦してわかりました。

どうしたか

  • 冒頭に記載したように、ルートディレクトリ直下にgo.modファイルを置き、アプリケーションを収めるcmdディレクトリと、パッケージを収めるpkgディレクトリを配置しました。
  • その上でgo.modファイル、各.goファイル中で以下のような記述を行い、必要なパッケージを参照します。なお、プロジェクト全体を非公開で運用する予定のため、モジュール名はgithub.com/~~の形式を取らないようにしました。
    • モジュール名の中で宣言するルートディレクトリ名にドットを含んでいないと怒られるので、今回はproject.rootという名前にしています。(前提としてモジュール名とディレクトリ名は一致させています)
go.mod
module project.root
project.root/cmd/SAM_project1/lambda1/main.go
package main

import (
    "project.root/pkg/package1"
    "project.root/pkg/package2"
)

func main(){
    package1.hoge()
    package2.fuga()
}
  • 自分が分からなかったのは、同じモジュール配下であれば、例えローカルにしかないパッケージであっても、モジュール内の絶対パスを記述することでインポートできるということでした。
    • それまではたくさんのgo.modを作り=たくさんのモジュールを作り、他のローカルモジュールを参照するために、それぞれのgo.modファイル内でreplaceディレクティブを使ってパスを指定していました。

おわりに

  • 移行作業は面倒でしたが、おかげでプロジェクト全体がスッキリとしました。

Discussion

ログインするとコメントできます