【Golang】ローカル自作パッケージを使おうとすると「package XXX/ZZZZ is not in std」になる

1418 語
7 分
【Golang】ローカル自作パッケージを使おうとすると「package XXX/ZZZZ is not in std」になる

はじまり#

リサちゃん avatar
リサちゃん
ちょっと、全然パッケージを使えないんですが・・・
135ml avatar
135ml
新しいプログラミング言語の使い始めあるあるだな。

※当ページはアフィリエイト広告を利用しています。

想定する読者#

Go 言語を始めたての初心者

まず、何が起きてるんだ#

最近まで、 Python を書いていましたが、処理速度とメモリ節約に関する冒険がしたくなり、 Go を使い始めました。

そこで、自分で書いたローカルパッケージをmain.goなどで使おうとした時の話です。

話題のランタイム環境は、 Go 1.22.2 です。

はい、まずは憎きこのエラー文からです。

main.go:9:3: package mymodule/mypkg is not in std (/usr/local/go/src/mymodule/mypkg)

もしくは、 VSCode 上で表示されるこのエラー文。

could not import mymodule/mypkg (no required module provides package "mymodule/mypkg")

コイツらを乗り越えて、 Go を実行したい!

まずは結論から。#

結論としては、以下のディレクトリ構成で以下のようにファイルを設定すれば出来ました。

ディレクトリ構成:

mymodule
|--go.mod
|--go.sum
|--main.go
|--mypkg
| |--tools.go
go.mod
module mymodule
go 1.22.2
require (
github.com/google/go-github v17.0.0+incompatible
golang.org/x/oauth2 v0.19.0
)
require github.com/google/go-querystring v1.1.0 // indirect
main.go
package main
import (
"fmt"
"mymodule/mypkg"
"github.com/google/go-github/github"
"golang.org/x/oauth2"
)
// ...略
func main() {
fmt.Println(mypkg.Hello())
}
mypkg/tools.go
package my
// ...略
func Hello() string {
return "Hello, world!"
}

そして、内部パッケージを導入する際には、以下の4点に気を付ければ良いのかなと思いました。

  • 自作パッケージの中のファイル名は何でも良い: mypkgディレクトリ内にあるファイル名はtools.goですし、そのファイルのpackage文にmypkgは書いてありません。しかし、プログラムとしては問題なく動きます。ビルドしても動きます。
  • 自作パッケージの中にgo.modは不要である: 自作パッケージのディレクトリにgo.modが無ければ、親ディレクトリを見に行きます。モジュール全体で必要な外部パッケージが分からなくなるので、go.modはルートディレクトリだけに置かれるのが良さそうだと思いました。
  • go.mod内のmoduleの値が重要である: ここのモジュール名から、直下のサブディレクトリを参照していきます。
  • main.goimport文にはディレクトリ名を書く: 僕の場合はファイル名を書いていて沼りました。

自作パッケージを使用するまでの手順#

それでは、細かいところを手順立てていきましょう。

1. パッケージの設定#

mypkgディレクトリにあるtools.goファイルでパッケージを定義します。ファイルの先頭に以下のように記述します。

mypkg/tools.go
package my
// ...略
func Hello() string {
return "Hello, world!"
}

ここで、package文には、mypkgではなくmyと書きました。外部パッケージとして利用する場合にどうなるかはちょっと分かりませんが、ただ内部で動かす時は問題なく動きます。

2. main.goでのパッケージのインポート#

そして、main.goにこんな感じで書きます。

main.go
package main
import (
"fmt"
"mymodule/mypkg"
"github.com/google/go-github/github"
"golang.org/x/oauth2"
)
// ...略
func main() {
fmt.Println(mypkg.Hello())
}

そうしたら、必要な外部パッケージのインポートがまだ出来ていないので、go mod initでインストールおよびインポートします。

3. go.modでモジュールを明示する#

ここで、go mod initを使うと、このようなメッセージが返ってきますよね。

go: cannot determine module path for source directory /home/username/mymodule (outside GOPATH, module path must be specified)
Example usage:
'go mod init example.com/m' to initialize a v0 or v1 module
'go mod init example.com/m/v2' to initialize a v2 module
Run 'go help mod init' for more information.

自分は当初、これはおまじないのようなものだと思っていましたが、ここでgo mod initの引数に渡す文字列がモジュール名になるようです。この部分がとても大事です。

なので、go mod init <モジュール名>を実行して、

Terminal window
go mod init mymodule

すると、こんな感じでメッセージが返ってきます。go.modも作成されます。

go: creating new go.mod: module mymodule
go: to add module requirements and sums:
go mod tidy

しかし、必要なパッケージがまだインストールされていないので、go mod tidyをして必要なパッケージを全て入れます。

Terminal window
go mod tidy

go mod tidyをすると、go.modmain.goの処理に必要なパッケージが列挙されて、未インストールのものはインストールされます。

go.modの中にはこんな感じで記述されているかと思います。

module mymodule
go 1.22.2
require (
github.com/google/go-github v17.0.0+incompatible
golang.org/x/oauth2 v0.19.0
)
require github.com/google/go-querystring v1.1.0 // indirect

ここで、go.modには内部パッケージの情報は記されていないことが分かります。

しかし、go.modが存在している状態では、そのパッケージ全体はモジュールモードとなり、module文に記述されている文字列がモジュール名になるわけです。(go.modが存在していないと、GOPATHモードになるみたいです。ちょっと、そのモードで弄る気力は持ち合わせていない。)

モジュールモードでは、このモジュール名から内部パッケージを参照していきます。なので、"mymodule/mypkg"mypkg内にあるtools.goを参照できるというわけです。

これで動くようになりました!

まとめ#

Go 言語でローカルの自作パッケージをインポートする方法を紹介しました。以下にポイントをまとめます。

  • 自作パッケージの中のファイル名とpackage名は、適当に付けても動くことは動く。
  • 自作パッケージの中にgo.modは不要である
  • go.mod内のmoduleの値およびgo mod initの引数が重要である。
  • main.goimport文にはディレクトリ名を書く。

この内部パッケージのインポートの作業でかなり時間を無駄にしたので、同じように無駄にする人が一人でも減れば嬉しいですね・・・!

プログラミングのお供に#

PFU キーボード HHKB Professional HYBRID 日本語配列/墨amzn.to
Amazon.co.jpで購入する
【Amazon.co.jp限定】 Logicool G ゲーミングキーボード G515 TKL 薄型 有線 テンキーレス キーボード G515-LNBK リニア 赤軸 静かなタイピング 日本語配列 LIGHTSYNC RGB ゲーミング メカニカルキーボード PC window mac chrome ブラック 国内正規品amzn.to
Amazon.co.jpで購入する
ZENAIM KEYBOARD ゼンエイムキーボード【MOTION HACK機能(ラピッドトリガー機能)搭載/0.05mm単位のアクチュエーション可変/温度補正機能による誤動作防止/磁気検知式ロープロファイルキーボード/TKLサイズ/日本語配列/脱着式Type-Cケーブル/安心の国内サポート】amzn.to
Amazon.co.jpで購入する

おしまい#

リサちゃん avatar
リサちゃん
いっつもこういう所に詰まるんだよなあ~!!
135ml avatar
135ml
動かせてしまえればコッチのもの。

以上になります!

記事を共有

この記事が役に立ったなら、ぜひ他の人と共有してください!

【Golang】ローカル自作パッケージを使おうとすると「package XXX/ZZZZ is not in std」になる
https://endorphinbath.com/posts/golang-import-local-package/
著者
kinkinbeer135ml
公開日
2024-05-01
ライセンス
CC BY-NC-SA 4.0
関連記事 スマート
1
【Cloud SQL】GolangでDBインスタンスの開始停止をスケジュール実行して節約する
Code Golangで書いたCloud Run FunctionでCloud SQLインスタンスの起動と停止を行い、Cloud SchedularとPub/Subでスケジュール実行してコスト削減を図ります。
2
【Cloud SQL】GolangでDBインスタンスへのオペレーション完了まで待つ
Code Go言語でCloud SQLに作成したDBインスタンスに対する処理が完了するまで待つようにします。「Error 409: Operation failed because another operation was already in progress. Try your request after the current operation is complete., operationInProgress」というエラーを回避します。
3
【Go、Docker】「api」という名前のパッケージを作るとビルド出来なくなる
Code Goでアプリケーションを開発する際、「api」というパッケージ名を含んだモジュールをDockerコンテナ内でビルドしようとするとバグります。そんな奇妙な事象に遭遇して沼りました。
4
【Go】日付計算とかWeb検索とかするMCPサーバを手に入れた
Code GoでClineに利用出来るMCPサーバを作りました。年月日の計算やBraveのAPIを使ってWeb検索が出来るようになっています。
5
【Cloud SQL】GolangでDBインスタンスの開始停止をDiscordで通知する
Code Go言語でCloud SQLに作成したDBインスタンスを自動で開始および停止するCloud Run Functionsが実行された時に、Discord上で通知を飛ばす機能を実装する手順を紹介します。
ランダム記事 ランダム
Profile Image of the Author
kinkinbeer135ml
SIerをやめて、プログラミングを勉強しています。※Amazonアソシエイトに参加しています。
お知らせ
私のブログへようこそ!これはサンプルのお知らせです。
音楽
カバー

音楽

再生中なし

0:00 0:00
歌詞なし
カテゴリ
タグ
サイト統計
記事
287
カテゴリー
8
タグ
93
総文字数
486,174
運用日数
0
最終活動
0 日前

目次