golang パッケージのimport(go.modとgo.sumから体系的に理解)
go.modとgo.sumの役割
本題に入る前に、go.modとgo.sumについて理解します(これを理解したほうが早い)
go.modとgo.sumは、Goプロジェクトの依存関係管理において重要な2つのファイルです。それぞれの役割と違いを簡単に表にまとめます。
ファイル名 | 役割 |
---|---|
go.mod | 依存モジュール名とバージョンを管理する宣言ファイル。プロジェクトの依存関係を記録。 |
go.sum | 依存モジュールのハッシュ値を管理。改ざん防止・ビルドの再現性担保のためのファイル。 |
イメージしやすい例え
-
go.mod:これは「犬の血統書」にあたります。
どの犬種(ライブラリ)で、どんな親(バージョンや依存関係)から生まれたかが記録されています。
つまり、「この犬(プロジェクト)は、どんな血筋(依存関係)を持っているか?」を示すものです。
-
go.sum:これは「血統書の真偽を証明する鑑定書」です。
血統書(go.mod)に書かれている内容が本当に正しいものか、偽物や改ざんがないかを証明するための「保証書」や「認証スタンプ」のようなものです。
これがあることで、「この犬の血統書は本物ですよ!」と誰にでも証明できます。
go.mod
↓こんな感じで書かれています
module github.com/ユーザー名/GoProject
go 1.20
require (
github.com/gin-gonic/gin v1.8.1
github.com/sirupsen/logrus v1.9.0 // indirect
)
- これがあることで、誰がどこでビルドしても「同じ依存関係」で開発・ビルドできます。
go.sum
↓こんな感じで書かれています
github.com/gin-gonic/gin v1.8.1 h1:xxxxxxxxxxxxxxxxxxxx
github.com/gin-gonic/gin v1.8.1/go.mod h1:xxxxxxxxxxxxxxxxxxxx
- セキュリティや再現性の観点から、go.sumもリポジトリに含めて管理するのが推奨されています。
両ファイルの管理について
- go.modとgo.sumの両方を、Gitなどのバージョン管理システムで管理(コミット)するのがベストプラクティスです。
- go.sumがなくてもビルドは可能ですが、再現性・安全性のため必ずgo.sumも管理しましょう。
この2つをセットで管理することで、誰がどこでビルドしても「同じものが安全に作れる」ようになります
go.modの記載内容について掘り下げ
moduleとrequireの違い
記述 | 役割・意味 |
---|---|
module | このプロジェクト(モジュール)自体の名前(公開場所やID)を指定します。通常はリポジトリのURL(例:github.com/ユーザー名/プロジェクト名)です。プロジェクト全体の「名前札」のようなものです。 |
require | このプロジェクトが利用する外部モジュール(ライブラリ)と、そのバージョンを指定し、どんな依存関係があるかを明示します。複数行記載でき、直接・間接依存も含まれます。 |
パッケージ(package)管理について
Goにおいて「package(パッケージ)」の管理は「module(モジュール)」で行います。
moduleが管理するもの(極論:main.goより下にあるフォルダ=パッケージ)
モジュールは、複数のパッケージをまとめた単位であり、プロジェクト全体や配布・バージョン管理の単位です。go.modファイルがあるディレクトリ以下のすべてのパッケージを「1つのモジュール」として管理します。
以下のようなフォルダ構成を例に説明します
your-module/
├── go.mod ← モジュール管理ファイル
├── main.go ← mainパッケージ(実行ファイルのエントリポイント)
├── config/ ← パッケージ1
│ └── config.go
└── models/ ← パッケージ2
├── user.go
└── todo.go
下図のようにmodueは、mainパッケージ・configパッケージ・modelsパッケージをまとめます(main.goより下にあるフォルダ=パッケージと思ってよい)
[ モジュール(your-module) ]
│
├─ go.mod
├─ [main パッケージ]
│ └─ main.go
├─ [config パッケージ]
│ └─ config.go
└─ [models パッケージ]
├─ user.go
└─ todo.go
パッケージの宣言
それぞれのパッケージにぶら下がるmai.go やuser.goのような.goファイルは
1行目に、自身の属するパッケージを宣言します。
//main.goの場合
package main ←ここ
import("***")
//config.goの場合
package config ←ここ
import("***")
go.modファイルの”moduleディレクティブ”の書き方
↓前に出した例をもう一度出すね。
(以下の”github.com/ユーザー名/GoProject”のところの話)
module github.com/ユーザー名/GoProject
go 1.20
require (
github.com/gin-gonic/gin v1.8.1
github.com/sirupsen/logrus v1.9.0 // indirect
)
ここには、そのプロジェクト(モジュール)の名前(モジュールパス)を定義します。通常、ここにはGitHubなどのリポジトリパスや、プロジェクトを一意に識別できる名前を指定します。
同じmoduleで管理されているパッケージを使う方法
いよいよ本題、LocalPackageのimportについてです。
Goでは、ローカルパッケージを使用する場合、以下のようにimportする必要がります。
import "<モジュール名>/<パッケージ名>"
の形式で記述します。
your-module
、パッケージ名がconfig
の場合
例:モジュール名がgopackage main
import (
"fmt"
"your-module/config"
)
func main() {
fmt.Println(config.YourFunction()) // configパッケージ内の関数を呼び出す
}
-
<モジュール名>
はgo.modのmoduleディレクティブで指定した名前(例:your-moduleやgithub.com/ユーザー名/プロジェクト名)です。 -
<パッケージ名>
はディレクトリ名(例:config)です
Discussion