go.modのreplaceでローカルにある別プロジェクトにアクセスする
go.modはgithub等外部にあるパッケージをプロジェクトに追加することができます。
外部ではなく、ローカルにある別プロジェクトにもアクセスできるか調べました。
ディレクトリ構成
.
├── project1
│ ├── aaa.go
│ ├── go.mod
│ └── iii
│ └── iii.go
└── project2
├── go.mod
└── main.go
project2のmain.goからproject1のaaa.goとiii/iii.goにアクセスします。
簡単なproject1の中身から見ていきます。
project1
go.mod
module project1
go 1.17
go mod init project1
を実行すると作成されるgo.modです。
go.modが無いとproject2にgoのプロジェクトとして認識されないので作成しました。
aaa.go
package aaa
import "fmt"
func ShowText() {
fmt.Println("project1/aaa.goです。")
}
packageはaaaです。
publicメソッドの必要があるのでShowTextメソッドの先頭文字(S)は大文字にして下さい。
iii/iii.go
package iii
import "fmt"
func ShowText() {
fmt.Println("project1/iii/iii.goです。")
}
packageはiiiです。
iii.goを配置するディレクトリ名をパッケージ名と合わせました。
project2
go.mod
module project2
go 1.17
require project1 v0.0.0
replace project1 => ../project1
project2のgo.modです。
require
go buildを実行した時にパッケージが無く自動取得、またはgo getで指定したパッケージを取得した時に、パッケージ情報がrequire部分に記述されます。
今回はローカルにあるプロジェクトにアクセスしたいので任意の名前とバージョンを手入力します。
require [任意のパッケージ名] v[x.x.x]
replace
外部パッケージに対しては、バージョンを置き換えるのに使うことが多いようです。
今回はreplaceを使って、先ほどrequireで作成したproject1パッケージにPathを指定します。
replace [パッケージ名] => [ローカルプロジェクトのPath]
main.go
package main
import (
"fmt"
aaa "project1"
"project1/iii"
)
func main() {
fmt.Println("project2のmainです。")
aaa.ShowText()
iii.ShowText()
}
先ほどgo.modのrequireで作成したproject1をimportで使います。
project1/iii/iii.goのほうはディレクトリ名(iii)とパッケージ名(iii)が一致しているため、パッケージ名.メソッド()という形でメソッドにアクセスできます。
project1/aaa.goのようにディレクトリ名(project1)とパッケージ名(aaa)が不一致の場合は、エイリアスをパッケージ名の左側にエイリアスを記述する必要があります。
やってみる
project2ディレクトリに移動し実行します。
project2 % go run main.go
project2のmainです。
project1/aaa.goです。
project1/iii/iii.goです。
project2のmain.goからproject1の格パッケージへアクセスすることができました。
モジュールの管理や各ファイルへのアクセス方法についてはまだまだ分からないことばかりなので少しずつ調査を進めていこうと思います。
internal package
golangには外部プロジェクトからのアクセスを許可したくないファイルを守るinternal packageという機能があります。
internalという名前のディレクトリにファイルを配置するだけで良いそうです。
.
├── project1
│ ├── aaa.go
│ ├── go.mod
│ ├── iii
│ │ └── iii.go
│ └── internal
│ └── uuu.go
└── project2
├── go.mod
└── main.go
package main
import (
"fmt"
aaa "project1"
"project1/iii"
uuu "project1/internal"
)
func main() {
fmt.Println("project2のmainです。")
aaa.ShowText()
iii.ShowText()
uuu.ShowText()
}
internalディレクトリにuuuというパッケージのファイルを作成しました。
実行してみます。
% go run main.go
package command-line-arguments
main.go:7:2: use of internal package project1/internal not allowed
internal packageにより、project1/internalへのアクセスは拒絶されました。
参考
Discussion