はじめに
Go言語でパッケージを作ろうとした時に、一度は遭遇するであろうcannot find package
エラー。
僕自身も同じエラーに遭遇し、最初は??でした。
この経験から学んだパッケージの作り方(ファイル、ディレクトリの配置、パッケージ名など)を簡単にまとめます。
エラーの原因とソリューション
ファイルを分割した際にこのエラーに出くわす可能性がある。それは、別ファイルに切り出したパッケージの配置場所に問題があることが多々。その場合、分割したファイルは、main.go
ファイルと同列に配置してはならず、パッケージ名と同じ名前のディレクトリを作成し、その下に分割したファイルを配置するとエラーを解消できる。
文面だとわかりにくい点もあるかと思うから、実際に簡単なソースコードを準備して確認しよう。
プログラムの準備
最初に、go-test
フォルダを作り、その配下にmain.go
ファイルを準備する。
❯ pwd
/Users/takuyanin/go/src
❯ mkdir go-test
❯ cd go-test
❯ touch main.go
そして、簡単にコーディングをし、
package main
import "fmt"
func main() {
hoge()
fuga()
}
func hoge() {
fmt.Println("Hello hoge!")
}
func fuga() {
fmt.Println("Hello fuga!")
}
実行してみる。
❯ go run main.go
Hello hoge!
Hello fuga!
このように、main.goファイルに全てのソースコードを書いている場合は問題はないだろう。
次に、問題の、ファイルを分割する場合を見てみる。
ファイルを分割する
ファイルをそれぞれ同列に配置。
❯ tree
/Users/takuyanin/go/src/go-test
|--hogefuga.go
|--main.go
プログラムは関数を別パッケージに切り出す。
package main
import "./hogefuga"
func main() {
hogefuga.Hoge()
hogefuga.Fuga()
}
package hogefuga
import "fmt"
func Hoge() {
fmt.Println("Hello hoge!")
}
func Fuga() {
fmt.Println("Hello fuga!")
}
そして、実行すると、例のエラーに遭遇。
❯ go run main.go
main.go:3:8: cannot find package "./hogefuga" in:
/Users/takuyanin/go/src/go-test/hogefuga
解決
パッケージ名と同名のディレクトリを準備し、その下に分離したパッケージを移動する。
❯ mkdir hogefuga
❯ ls
hogefuga/ hogefuga.go main.go
❯ mv hogefuga.go hogefuga/
❯ ls
hogefuga/ main.go
要は、配置が下記のようになっていればOK。
❯ tree
/Users/takuyanin/go/src/go-test
|--hogefuga
| |--hogefuga.go
|--main.go
実行すると、期待通りに動く。
❯ go run main.go
Hello hoge!
Hello fuga!
Goのパッケージの作り方
上で見たように、分離したパッケージ名 = ディレクトリ名
となっていることが必要。
王道の作り方
ディレクトリ名 = ファイル名 = パッケージ名
。
❯ tree
/Users/takuyanin/go/src/go-test
|--hogefuga
| |--hogefuga.go
|--main.go
しかし、ファイル名は同名でなくても良いことに注意。
例えば、hogefuga.goのファイル名をpiyo.goに変更しても同様の結果が得られる。
❯ tree
/Users/takuyanin/go/src/go-test
|--hogefuga
| |--piyo.go
|--main.go
❯ go run main.go
Hello hoge!
Hello fuga!
分割するファイルを増やす
また、次のように分離するファイルが増えたとしても問題ない。
❯ tree
/Users/takuyanin/go/src/go-test
|--hogefuga
| |--fuga.go
| |--hoge.go
|--main.go
ソースコードは下記のような感じ。
main.go
は変更なし。
package main
import "./hogefuga"
func main() {
hogefuga.Hoge()
hogefuga.Fuga()
}
package hogefuga
import "fmt"
func Hoge() {
fmt.Print("Hello hoge\n")
}
package hogefuga
import "fmt"
func Fuga() {
fmt.Print("Hello fuga\n")
}
これでわかるように、同名のパッケージ名を複数回使うことができる。
おわりに
他の言語にはない仕様であるため、Goでプログラムを組む際、同じようなに躓く人は割といるのではないかと思い記事にまとめてみました。再度まとめると、
・ディレクトリを準備し、パッケージ名 = ディレクトリ名
とし、構成に留意する
これで、Go言語で、簡単なプロジェクトなら作れるようになると思います。おわり。