[Golang] Module

2021-11-02 hit count image

GolangでModule(モジュール)について説明して、どう使えるか紹介します。

概要

今回のブログポストではGolangでModule(モジュール)を使う方法について説明します。このブログポストで紹介するコードは次のリンクで確認できます。

モジュール

Golangのバージョン1.11以前にはモジュールと言うありませんでした。1.11バージョンで初めてモジュールが紹介され、1.13でモジュール機能が完成されました。1.13ではモジュールはOptional機能でしたが、1.16バージョンからGolangの基本仕様になりました。

Golangでモジュールはパッケージ(Package)の集まりで、1つのモジュールは複数のパッケージを含むことができます。このモジュールを使ってGolangではパッケージの依存関係を管理することができ、モジュールはパッケージ管理システムとして活用されてます。

モジュールはパッケージをツーリとして管理して、ルート(root)フォルダにgo.modファイルを生成してモジュールを定義して、依存関係を管理します。

go mod init

Golangでは次のコマンドを使ってモジュールを生成することができます。

go mod init MODULE_NAME

この時モジュールの名前はユニークである必要があります。したがって、GitHubのレポジトリを活用したり何かのURLをモジュール名前として使います。

go mod init github.com/dev-yakuza/study-golang/module/greeting

greetingモジュール

そしたら、例題を作ってみてGolangのモジュールを理解してみましょう。まず、他のモジュールで参照するgreetingモジュールを作ってみます。

mkdir greeting
cd greeting
touch main.go

greetingモジュールを作るためgreetingフォルダを生成してgreetingフォルダ中にmain.goファイルを生成して次のように修正します。

package greeting

import "fmt"

func Hello(name string) string {
  message := fmt.Sprintf("Hello, %s", name)
  return message
}

greetingモジュールはgreetingと言うパッケージを持っています。

package greeting

greetingのパッケージにはHelloと言う関数があり、その関数は他のパッケージでも使えるようにPublic関数(大文字で始まる)で作成されてます。

func Hello(name string) string {
  message := fmt.Sprintf("Hello, %s", name)
  return message
}

Hello関数はnameパラメーターを貰ってHello, NAMEで文字列をリターンします。

greetingモジュール生成

このように作成したgreetingパッケージを次のコマンドを使ってモジュールを生成します。

# cd greeting
go mod init github.com/dev-yakuza/study-golang/module/greeting

コマンドを実行すると、当該フォルダにgo.modファイルを生成されることが確認できます。

module github.com/dev-yakuza/study-golang/module/greeting

go 1.17

hello モジュール

次はgreetingモジュールを使うhelloモジュールを生成してみましょう。

# cd ..
mkdir hello
cd hello
touch main.go

greetingフォルダと同じ位置にhelloフォルダを生成します。そして、生成したフォルダにmain.goファイルを生成して次のように修正します。

package main

import (
  "fmt"

  "github.com/dev-yakuza/study-golang/module/greeting"
)

func main() {
  message := greeting.Hello("John")
  fmt.Println(message)
}

このように作ったhelloモジュールはmainパッケージとmain関数を持っています。つまり、プログラムをスタート時点を持ってることを意味します。このプログラムは私たちが先ほど作ったgreetingモジュールを使う予定です。greetingモジュールを使うため、上で作ったモジュールの名前を使います。

import (
  "fmt"

  "github.com/dev-yakuza/study-golang/module/greeting"
)

そしてgreetingモジュールが提供するHello関数を使ってメッセージを出力します。

func main() {
  message := greeting.Hello("John")
  fmt.Println(message)
}

このようにプログラムを作成したら次のようにgreetingパッケージを探せないエラーが発生します。

could not import github.com/dev-yakuza/study-golang/module/greeting (cannot find package "github.com/dev-yakuza/study-golang/module/greeting" in any of
  /usr/local/Cellar/go/1.17/libexec/src/github.com/dev-yakuza/study-golang/module/greeting (from $GOROOT)
  /Users/jeonghean/go/src/github.com/dev-yakuza/study-golang/module/greeting (from $GOPATH))compilerBrokenImport

次はhelloモジュールを作成して、greetingモジュールを使えるように修正してみましょう。

helloモジュール生成

下記のコマンドを使ってhelloモジュールを生成します。

go mod init github.com/dev-yakuza/study-golang/module/hello

コマンドを実行すると、helloフォルダの中にgo.modファイルが次のように生成されることが確認できます。

module github.com/dev-yakuza/study-golang/module/hello

go 1.17

go mod tidy

Golangで基本的に提供されるパッケージではなく、外部のパッケージを使う時、当該パッkー時をダウンロードする必要があります。この時、モジュール中で次のコマンドを実行して外部パッケージをダウンロードします。

go mod tidy

しかし、私たちが作ったgreetingパッケージはまだ公開されてないので(GitHubなどにコードを公開してないので)、次のようなエラーが出ます。

go: finding module for package github.com/dev-yakuza/study-golang/module/greeting
github.com/dev-yakuza/study-golang/module/hello imports
        github.com/dev-yakuza/study-golang/module/greeting: module github.com/dev-yakuza/[email protected] found (v0.0.0-20211026013945-559aef3c74a0), but does not contain package github.com/dev-yakuza/study-golang/module/greeting

この場合は、greetingモジュールをGitHubに上げて、外部に共有することで解決することもできます。他の方法はgo.modを使ってローカルパッケージを参照するように変更することです。

go mod edit -replace

そしたら、go.modを使ってローカルパッケージを参照するように変更してみます。次のコマンドを実行して、ローカルパッケージを参照するように変更します。

go mod edit -replace github.com/dev-yakuza/study-golang/module/greeting=../greeting

そして再び、次のコマンドを実行してパッケージを設定します。

go mod tidy

実行

全ての準備が終わりました。今まで作業した内容を確認するためhelloフォルダで次のコマンドを実行してみます。

# cd hello
go run main.go

このように実行したら、次のような結果が出力されます。

Hello, John

外部モジュールのフォルダー

Golangで次のコマンドを実行すると外部で作成されたモジュールがダウンロードされ、プログラムで使えることができます。

go mod tidy

このようにダウンロードされたモジュールはGOPATH/pkgに保存されます。

go env

上のコマンドを実行すると次のようにGOPATHのパスが分かります。当該フォルダに移動するとpkgフォルダを確認できます。

...
GOOS="darwin"
GOPATH="/Users/dev-yakuza/go"
GOPRIVATE=""
...

完了

これでGolangでモジュールでは何か、どう使うのかについてみてみました。今からはモジュールを使って外部のパッケージを使ってみたり、外部で使えるパッケージを提供してみてください。

私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!

Posts