【Go言語】GOPATHの外に作ったプロジェクトでサブパッケージをインポートする
Go言語に入門中の身です。A Tour of Goをやり終えたところです。
手元のお試し用のコードが増えるにつれて、main.go
ファイルに収まらなくなり、ファイルを分割したい欲求にかられ始めた頃、壁にぶつかりました。
ローカルファイルのインポートができない!
ソースコードを以下のように配置して……
zenn-first-article
├── main.go
└── zenn
└── zenn.go
// zenn.go
package zenn
// Article describes a zenn article meta
type Article struct {
Slug string
Title string
Emoji string
Type string
Topics []string
Published bool
}
main.go
から./zenn/zenn
のようにインポートすると……
// main.go
package main
import (
"fmt"
"./zenn/zenn"
)
func main() {
fmt.Println("Hello, Zenn!")
item := zenn.Article{}
fmt.Printf("%v\n", item)
}
以下のようなエラーが発生。。
main.go:6:2: local import "./zenn/zenn" in non-local package
exit status 1
Process exiting with code: 1
GOPATHとは一体……?
golang import local package
などと検索してみても、いまいちピッタリはまる情報がヒットしません。どうにか得られた情報はこんな感じ
- 環境変数GOPATHにセットしたパスの下にすべてのプロジェクトを配置するのが基本
- ローカルパッケージをインポートするときも($GOPATH/src以下からの)絶対パスを使う
- ローカルパッケージのインポートでも相対パスは非推奨
- バージョン1.11から導入されたgo modulesという仕組みがある
- go modulesを使うと、プロジェクトをGOPATHの外に配置できる
go modulesを試してみる
「GOPATH(何も設定しなければ、~/goになる)の下に全部のプロジェクトを置く?!なにそれ!」
「ローカルパッケージの相対パスでのインポートは非推奨?!」
などとびっくりしつつ……
go modulesというのを使えばよいのね。と思いながら使い方を調べると、GitHubなどにホスティングされている外部パッケージを管理する仕組みのようです。
しかし、自分で作成したローカルパッケージをインポートする方法がいまいちわからない。。
たしかに$GOPATH/src/zenn-first-article
にプロジェクトのディレクトリを配置すれば、
// main.go
package main
import (
"fmt"
"zenn-first-article/zenn"
)
のようにインポートできるようにはなるのですが、npmやbundlerのようなパッケージ管理ツールに慣れた身にとっては違和感がすごいです。
解決策
なんだかもんにょりして、Twitterでつぶやいたところ、親切な方がgo modules
の使い方を教えてくださいました!
なるほど!go modules
を初期化するときに指定したモジュール名がポイントになるようです。
教えていただいた通り、以下のように初期化を行うことでmodule名/パッケージ名
で無事インポートできるようになりました。
$ pwd
/Users/turara/Dev/Go/zenn-first-article
$ go mod init zenn-first-article // module名を指定
go: creating new go.mod: module zenn-first-article
$ cat go.mod
module zenn-first-article // module名がgo.modに記載される
go 1.15
package main
import (
"fmt"
"zenn-first-article/zenn" // module名/パッケージ名
)
のぼのぼ📡さん、ありがとうございました!
環境
go version go1.15.2 darwin/amd6
おまけ:Goの公開用パッケージの命名について
パッケージの命名について、はじめて知った面白い視点だったので紹介します。
Discussion