SE_BOKUのまとめノート的ブログ

SE_BOKUが知ってること・勉強したこと・考えたことetc

GO言語(golang)1.20をはじめる②:パッケージとモジュールを理解する

f:id:arakan_no_boku:20210412005751p:plain

目次

GO言語(golang)1.20をはじめる②:パッケージとモジュールを理解する

前回、GO言語の開発ができる環境を整えました。

arakan-pgm-ai.hatenablog.com

でも、GO言語の学習をすすめるには、まず「パッケージ」と「モジュール」が理解できてないとつらいので、まず整理しときます。

パッケージ

GO言語でコードをまとめる基本単位がパッケージ「pacage」です。

ソースコードの頭で、必ず

package xxxxxxxx

みたいに、パッケージ名を宣言しないといけません。

プログラムには必ず「main」パッケージが必要です。

この「main」パッケージ中には必ず「main」関数の定義が必要です。

この「main」パッケージの「main」関数がプログラムのエントリーポイントです。

mainパッケージ以外のパッケージには「main」関数)を置きません。

mainパッケージを補助するパッケージになります。

モジュール

GO言語(Golang)のモジュールはパッケージ(Package)の集まりです。

モジュールはフォルダとして作成し、そのルート(root)フォルダにgo.modファイルを生成することでモジュールを初期化します。

コマンドは

go mod init <MODULE_NAME>

です。

モジュール名(<MODULE_NAME>)の部分はユニークである必要があります。

モジュール名にはモジュールの公開パスを指定するのが正確です。

例えば、GitHubリポジトリで公開するのであれば。

go mod init github.com/boku/module_name

みたいな感じです。

でも、公開前提でなければパスでなくても問題ありません。

例えば「hello」モジュールであれば

go mod init hello

のようにモジュール名だけでもいいですし

go mod init boku/hello

のようにパスの部分に自分を識別する情報をいれてもよいです。

気を付けないといけないのは、mainパッケージで「import」して使うモジュールを作るときの指定の仕方です。

go mod init github.com/boku/module_name

のように、参照パスを正確に指定して書いているとします。

そのモジュールをimportして使うには、ソースの中で以下のように書きます。

import (
  "fmt"

  "github.com/boku/module_name"
)

外部モジュールをインストールして使うには

  • go get [パッケージ名] :  指定したパッケージをインストールする
  • go get   : importに記載されたパッケージをインストールする
  • go mod tidy :  import記載パッケージのインストールと不要なパッケージの削除

を行いますが、その時にまだGitHubリポジトリにアップしていないと指定場所にない「could not import 」エラーになります。

ローカルにおいたモジュールをimportしてエラーにならない方法を以降で試します。

ローカルモジュールのimport例(1)

以下の簡単なモジュールを作って、mainパッケージにimportして使います。

ファイル名は「greeting.go」とします。

ackage greeting

import "fmt"

func Hello(name string) string {
	message := fmt.Sprintf("こんにちは。 %sさん", name)
	return message
}

 

最初は「hello」モジュール内にフォルダを作って分割するケースです。

フォルダ構成としては以下のようになります。

helloフォルダの「hello.go(mainパッケージ)」と同列に「greeting」フォルダを作り、その下に「greeting.go」を置きます。

gretingフォルダには「go.mod」ファイルはおきません。

そして、mainパッケージ「hello.go」では以下のように参照します。

package main

import (
	"boku/hello/greeting"
	"fmt"
)

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

importで「boku/hello/greeting」としている理由は、mainパッケージであるhelloモジュールを初期化するときに

go mod init boku/hello

としたからです。

こう書いても、VSCodeでエラー「could not import 」が表示される場合は、helloフォルダをカレントにして「go get」または「go mod tidy」を実行します。

これで実行「go run .」すると

と表示されました。

ローカルモジュールのimport例(2)

今後は同じ「greeting」モジュールを、helloの外においた場合です。

この場合は当然ながら、greetingフォルダで「go mod init」をする必要があります。

これがGitのリポジトリなら、そこを指すパスで初期化しますが、今回はその気はなくまったくのローカルです。

なので。

go mod init greeting

のようにモジュール名をそのまま指定します。

たまに「../greeting」みたいに相対パスで指定する例がネットにでている場合がありますが、古い情報です。

1.20だとエラーになるので注意してください。

go.modができたら、ワークスペースのカレントにある「go.work」ファイルに以下を追加します。

use .\src\greeting

ワークスペースに「src」フォルダがあって、その下に「greeting」フォルダを作っている想定なので、違う環境の場合は読み替えてください。

ここまでやったら、importを書き換えます。

importにはgreetingモジュールの「go.mod」ファイルに記載した名称を書きます。

package main

import (
	"fmt"
	"greeting"
)

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

変更したのはimport部分を「greeting」と、go.modを初期化するときに指定した名前にしただけです。

実行すると

同じ結果がかえります。

おまけ情報

外部パッケージを使うとき、Go 1.15まではgo buildでパッケージのインストールも行われましたが、Go 1.16からはgo buildによるパッケージのインストールはしません。

この記事の前提は「1.20」なので、パッケージのインストールが必要なGoファイルを実行する場合は「go mod tidy」か「 go get」をしてから「go build」しないといけないので注意が必要です。

今回はこんなところで。

ではでは。