Cou氏の徒然日記

ほのぼの日記ブログです。

Go言語の学習 その5 (パッケージ定義とパッケージインポート)

coublood.hatenablog.com

前回は、ローカルの別パッケージをimportして、その関数を呼び出すようにしてみました。

C:.
│  hello.go
│  main.go

└─print
        outmessage.go

Go言語はパッケージ周りに色々と制約が他にもあるので、このあたりをもう少し色々と見てみようかなと思います。

 

◆ 同一階層に複数パッケージ定義は不可

Javaとかは1ファイル1クラス以上の定義で、インポートするのはクラス単位のイメージでした。

ただ、Go言語だと、クラスではなくモジュール、インポート対象はパッケージ単位のようです。

そのため、同一ディレクトリ階層で複数のパッケージを定義するとダメなようです。

 

試しに

C:.
│  hello.go <- mainパッケージ
│  main.go <- main2パッケージ

のようにしてみると…

found packages main2 (hello.go) and main (main.go) in
C:\Study\Go\test1\main

つまり「test1\main階層に main2 と main という2つのパッケージがある」というエラーとなってしまいます。

そのため、同じ階層に配置するGoファイル(モジュール)のパッケージ名は統一する必要があります。

これは、ディレクトリ名と合わせることを推奨しているということでしょうね。

 

◆ 上位階層のパッケージをimport

今までの改装を1つ変更し、

C:.
│
├─main
│  │  hello.go
│  │  main.go  //参照元
│  │
│  └─print
│          outmessage.go
│
└─out
        outmessage.go  //参照先

main\main.go から out\outmessage.go を参照したい場合、パッケージの位置関係が今までのままだとうまく表現できません。

Go言語では、相対パスのパッケージimportは推奨されていないようです。

 

そのため、test1階層 (mainやoutのディレクトリ階層) でパッケージを定義する必要があります。

まずは test1階層で go mod init test1 を実行して、パッケージ定義を更新。

[go.mod] (test1階層)
module test1

go 1.22.2

階層構造とパッケージの関係はこうなるはずです。

C:.
│  go.mod  <- test1パッケージ
│
├─main
│  │  hello.go  <- test1/main パッケージ
│ │ main.go   <- test1/main パッケージ
│ │ │ └─print │ outmessage.go   <- test1/main/print パッケージ
│ └─out outmessage.go <- test1/main/out パッケージ

という関係になります。

 

[out\outmessage.go] (追加)
package out

import "fmt"

func OutGoodNight() {
	fmt.Println("Good Night.")
}

のように定義。

これを main\main.go から参照するには、以下のようにすればよさそうです。

(もともとの printパッケージも相対的に変わっているので…そこも修正)

[main\main.go (修正後)]
package main

import (
	"test1/main/print"    // test/print -> test/main/print
	"test1/out"   // 追加
)

func main() {
	//fmt.Println("Hello, world!")
	print_hello()
	print.Printmessage()
	out.OutGoodNight()   // outパッケージの関数呼び出し
}

これで実行すれば、無事に実行できていることが分かりました。

 

理解さえしてしまえば、それほど難しい話ではないですね。