できない.dev

Go の go run でパッケージが実行できない(package is not a main package)

`go run` は `package main` で `func main()` を持つパッケージしか実行できない。
ライブラリ側のディレクトリを指定したり、`package foo` のままだとこのエラーになる。

#run#package#main#build

公開:

要約

go run に渡したパッケージが package main でない、もしくは func main() を持っていないとこのエラーになります。
ライブラリ用パッケージは go run の対象にできません。
実行用エントリは必ず package mainfunc main() を持つ別ディレクトリ(例: cmd/myapp)に置きます。

// cmd/myapp/main.go
package main
 
func main() {
    // ...
}

よくある原因

  1. package main 宣言が無い: ライブラリ用のディレクトリで package foo のまま go run . を叩いた。
    Go はライブラリパッケージを直接実行する手段を持たない。
  2. func main() の欠落: 宣言は package main だが本体関数が無いと別バリエーションのエラー(function main is undeclared 等)になる。
  3. ディレクトリ指定が違う: モジュールルートで go run . を叩いたが、エントリは cmd/myapp/ 配下に置いていた。
  4. ファイル単体指定で関連ファイルが足りない: go run main.go だけ叩いたが、main から呼ぶ関数が別ファイルにある場合、それらも引数に並べる必要がある。

解決策

1. エントリポイントを cmd/ 配下に分離する

Go の慣習レイアウトでは、ライブラリ本体はモジュールルート直下、CLI エントリは cmd/<name>/main.go に置きます。

myapp/
├── go.mod
├── foo.go            // package myapp(ライブラリ)
└── cmd/
    └── myapp/
        └── main.go   // package main + func main()

実行は次の通り。

go run ./cmd/myapp

2. ファイル単体実行する場合

go run main.go helper.go

main パッケージ内のすべての .go ファイルを並べます。
ディレクトリ指定 (go run ./cmd/myapp) の方が漏れがなく安全です。

3. 「ビルドはできるが run できない」場合

ライブラリは go build ./... で型チェックは通りますが、go run は通りません。
CLI として動かしたいなら必ず main パッケージに分離してください。

この記事は役立ちましたか?