はじまり
ちょっと、全然パッケージを使えないんですが・・・
新しいプログラミング言語の使い始めあるあるだな。
※当ページはアフィリエイト広告を利用しています。
想定する読者
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.go
のimport
文にはディレクトリ名を書く。・・・僕の場合はファイル名を書いていて沼りました。
自作パッケージを使用するまでの手順
それでは、細かいところを手順立てていきましょう。
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 <モジュール名>
を実行して、
shell
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
をして必要なパッケージを全て入れます。
shell
go mod tidy
go mod tidy
をすると、go.mod
にmain.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.go
のimport
文にはディレクトリ名を書く。
この内部パッケージのインポートの作業でかなり時間を無駄にしたので、同じように無駄にする人が一人でも減れば嬉しいですね・・・!
プログラミングのお供に
PFU キーボード HHKB Professional HYBRID 日本語配列/墨
【Amazon.co.jp限定】 Logicool G ゲーミングキーボード G515 TKL 薄型 有線 テンキーレス キーボード G515-LNBK リニア 赤軸 静かなタイピング 日本語配列 LIGHTSYNC RGB ゲーミング メカニカルキーボード PC window mac chrome ブラック 国内正規品
ZENAIM KEYBOARD ゼンエイムキーボード【MOTION HACK機能(ラピッドトリガー機能)搭載/0.05mm単位のアクチュエーション可変/温度補正機能による誤動作防止/磁気検知式ロープロファイルキーボード/TKLサイズ/日本語配列/脱着式Type-Cケーブル/安心の国内サポート】
おしまい
いっつもこういう所に詰まるんだよなあ~!!
動かせてしまえればコッチのもの。
以上になります!
コメント